diff options
66 files changed, 30832 insertions, 0 deletions
diff --git a/engines/gnap/datarchive.cpp b/engines/gnap/datarchive.cpp new file mode 100644 index 0000000000..d480d31e67 --- /dev/null +++ b/engines/gnap/datarchive.cpp @@ -0,0 +1,121 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/dcl.h" +#include "common/file.h" +#include "common/stream.h" +#include "common/substream.h" +#include "gnap/datarchive.h" + +#include "engines/util.h" + +namespace Gnap { + +// DatArchive + +DatArchive::DatArchive(const char *filename) { +	_fd = new Common::File(); +	if (!_fd->open(filename)) +		error("DatArchive::DatArchive() Could not open %s", filename); +	_fd->skip(8); // Skip signature +	_fd->skip(2); // Skip unknown +	_fd->skip(2); // Skip unknown +	_entriesCount = _fd->readUint32LE(); +	debug(1, "_entriesCount: %d", _entriesCount); +	_fd->skip(4); // Skip unknown +	_entries = new DatEntry[_entriesCount]; +	for (int i = 0; i < _entriesCount; ++i) { +		_entries[i].ofs = _fd->readUint32LE(); +    	_entries[i].outSize1 = _fd->readUint32LE(); +    	_entries[i].type = _fd->readUint32LE(); +    	_entries[i].outSize2 = _fd->readUint32LE(); +	} +} + +DatArchive::~DatArchive() { +	_fd->close(); +	delete _fd; +	delete[] _entries; +} + +byte *DatArchive::load(int index) { +	_fd->seek(_entries[index].ofs); +	debug(1, "_entries[index].outSize2: %d; _entries[index].outSize1: %d", _entries[index].outSize2, _entries[index].outSize1); +	byte *buffer = new byte[_entries[index].outSize1]; +	if (!Common::decompressDCL(_fd, buffer, 0, _entries[index].outSize1)) +		error("DatArchive::load() Error during decompression of entry %d", index); +	return buffer; +} + +// DatManager + +DatManager::DatManager() { +	for (int i = 0; i < kMaxDatArchives; ++i) +		_datArchives[i] = 0; +} + +DatManager::~DatManager() { +	for (int i = 0; i < kMaxDatArchives; ++i) +		delete _datArchives[i]; +} + +void DatManager::open(int index, const char *filename) { +	close(index); +	_datArchives[index] = new DatArchive(filename); +} + +void DatManager::close(int index) { +	delete _datArchives[index]; +	_datArchives[index] = 0; +} + +byte *DatManager::loadResource(int resourceId) { +	const int datIndex = ridToDatIndex(resourceId); +	const int entryIndex = ridToEntryIndex(resourceId); +	return _datArchives[datIndex] ? _datArchives[datIndex]->load(entryIndex) : 0; +} + +uint32 DatManager::getResourceType(int resourceId) { +	const int datIndex = ridToDatIndex(resourceId); +	const int entryIndex = ridToEntryIndex(resourceId); +	return _datArchives[datIndex] ? _datArchives[datIndex]->getEntryType(entryIndex) : 0; +} + +uint32 DatManager::getResourceSize(int resourceId) { +	const int datIndex = ridToDatIndex(resourceId); +	const int entryIndex = ridToEntryIndex(resourceId); +	return _datArchives[datIndex] ? _datArchives[datIndex]->getEntrySize(entryIndex) : 0; +} + +int ridToDatIndex(int resourceId) { +	return (resourceId & 0xFFFF0000) >> 16; +} + +int ridToEntryIndex(int resourceId) { +	return resourceId & 0xFFFF; +} + +int makeRid(int datIndex, int entryIndex) { +	return (datIndex << 16) | entryIndex; +} + +} // End of namespace Gnap diff --git a/engines/gnap/datarchive.h b/engines/gnap/datarchive.h new file mode 100644 index 0000000000..2fd431bf70 --- /dev/null +++ b/engines/gnap/datarchive.h @@ -0,0 +1,80 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef GNAP_DATARCHIVE_H +#define GNAP_DATARCHIVE_H + +#include "common/array.h" +#include "common/events.h" +#include "common/file.h" +#include "common/memstream.h" +#include "common/random.h" +#include "common/str.h" +#include "common/substream.h" +#include "common/system.h" +#include "engines/engine.h" + +namespace Gnap { + +struct DatEntry { +    uint32 ofs; +    uint32 outSize1; +    uint32 type; +    uint32 outSize2; +}; + +class DatArchive { +public: +	DatArchive(const char *filename); +	~DatArchive(); +	byte *load(int index); +	int getCount() const { return _entriesCount; } +	uint32 getEntryType(int index) { return _entries[index].type; } +	uint32 getEntrySize(int index) { return _entries[index].outSize1; } +protected: +	Common::File *_fd; +	int _entriesCount; +	DatEntry *_entries; +}; + +const int kMaxDatArchives = 2; + +class DatManager { +public: +	DatManager(); +	~DatManager(); +	void open(int index, const char *filename); +	void close(int index); +	byte *loadResource(int resourceId); +	uint32 getResourceType(int resourceId); +	uint32 getResourceSize(int resourceId); +protected: +	DatArchive *_datArchives[kMaxDatArchives]; +}; + +int ridToDatIndex(int resourceId); +int ridToEntryIndex(int resourceId); +int makeRid(int datIndex, int entryIndex); + +} // End of namespace Gnap + +#endif // GNAP_DATARCHIVE_H diff --git a/engines/gnap/detection.cpp b/engines/gnap/detection.cpp new file mode 100644 index 0000000000..8898d9069a --- /dev/null +++ b/engines/gnap/detection.cpp @@ -0,0 +1,195 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" + +#include "common/config-manager.h" +#include "engines/advancedDetector.h" +#include "common/savefile.h" +#include "common/system.h" +#include "base/plugins.h" +#include "graphics/thumbnail.h" + +static const PlainGameDescriptor gnapGames[] = { +	{ "gnap", "Gnap" }, +	{ 0, 0 } +}; + +namespace Gnap { + +static const ADGameDescription gameDescriptions[] = { +	{ +		"gnap", "", +		{ +			{"stock_n.dat", 0, "46819043d019a2f36b727cc2bdd6980f", 12515823}, +			AD_LISTEND +		}, +		Common::EN_ANY, Common::kPlatformWindows, ADGF_NO_FLAGS, GUIO0() +	}, + +	AD_TABLE_END_MARKER +}; + +} // End of namespace Gnap + +class GnapMetaEngine : public AdvancedMetaEngine { +public: +	GnapMetaEngine() : AdvancedMetaEngine(Gnap::gameDescriptions, sizeof(ADGameDescription), gnapGames) { +		_singleid = "gnap"; +		_maxScanDepth = 3; +	} + +	virtual const char *getName() const { +		return "Gnap"; +	} + +	virtual const char *getOriginalCopyright() const { +		return "Gnap (C) 1999"; +	} + +	virtual bool hasFeature(MetaEngineFeature f) const; +	virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; +	virtual int getMaximumSaveSlot() const; +	virtual SaveStateList listSaves(const char *target) const; +	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; +	virtual void removeSaveState(const char *target, int slot) const; +}; + +bool GnapMetaEngine::hasFeature(MetaEngineFeature f) const { +	return +		false; +#if 0		 +	    (f == kSupportsListSaves) || +	    (f == kSupportsLoadingDuringStartup) || +	    (f == kSupportsDeleteSave) || +	    (f == kSavesSupportMetaInfo) || +	    (f == kSavesSupportThumbnail) || +	    (f == kSavesSupportCreationDate); +#endif	     +} + +void GnapMetaEngine::removeSaveState(const char *target, int slot) const { +	Common::String fileName = Common::String::format("%s.%03d", target, slot); +	g_system->getSavefileManager()->removeSavefile(fileName); +} + +int GnapMetaEngine::getMaximumSaveSlot() const { return 99; } + +SaveStateList GnapMetaEngine::listSaves(const char *target) const { +	Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); +	Common::StringArray filenames; +	Common::String pattern = target; +	pattern += ".???"; + +	filenames = saveFileMan->listSavefiles(pattern); +	sort(filenames.begin(), filenames.end());   // Sort (hopefully ensuring we are sorted numerically..) + +	SaveStateList saveList; +#if 0	 +	int slotNum = 0; +	for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) { +		// Obtain the last 3 digits of the filename, since they correspond to the save slot +		slotNum = atoi(filename->c_str() + filename->size() - 3); + +		if (slotNum >= 0 && slotNum <= 99) { +			Common::InSaveFile *file = saveFileMan->openForLoading(*filename); +			if (file) { +				int32 version = file->readSint32BE(); +				if (version != GNAP_SAVEGAME_VERSION) { +					delete file; +					continue; +				} + +				// read name +				uint16 nameSize = file->readUint16BE(); +				if (nameSize >= 255) { +					delete file; +					continue; +				} +				char name[256]; +				file->read(name, nameSize); +				name[nameSize] = 0; + +				saveList.push_back(SaveStateDescriptor(slotNum, name)); +				delete file; +			} +		} +	} +#endif +	return saveList; +} + +SaveStateDescriptor GnapMetaEngine::querySaveMetaInfos(const char *target, int slot) const { +#if 0 +	Common::String fileName = Common::String::format("%s.%03d", target, slot); +	Common::InSaveFile *file = g_system->getSavefileManager()->openForLoading(fileName); +	if (file) { + +		int32 version = file->readSint32BE(); +		if (version != GNAP_SAVEGAME_VERSION) { +			delete file; +			return SaveStateDescriptor(); +		} + +		uint32 saveNameLength = file->readUint16BE(); +		char saveName[256]; +		file->read(saveName, saveNameLength); +		saveName[saveNameLength] = 0; + +		SaveStateDescriptor desc(slot, saveName); + +		Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*file); +		desc.setThumbnail(thumbnail); + +		uint32 saveDate = file->readUint32BE(); +		uint16 saveTime = file->readUint16BE(); + +		int day = (saveDate >> 24) & 0xFF; +		int month = (saveDate >> 16) & 0xFF; +		int year = saveDate & 0xFFFF; + +		desc.setSaveDate(year, month, day); + +		int hour = (saveTime >> 8) & 0xFF; +		int minutes = saveTime & 0xFF; + +		desc.setSaveTime(hour, minutes); + +		delete file; +		return desc; +	} +#endif +	return SaveStateDescriptor(); +} + +bool GnapMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { +	if (desc) { +		*engine = new Gnap::GnapEngine(syst, desc); +	} +	return desc != 0; +} + +#if PLUGIN_ENABLED_DYNAMIC(GNAP) +	REGISTER_PLUGIN_DYNAMIC(GNAP, PLUGIN_TYPE_ENGINE, GnapMetaEngine); +#else +	REGISTER_PLUGIN_STATIC(GNAP, PLUGIN_TYPE_ENGINE, GnapMetaEngine); +#endif diff --git a/engines/gnap/fontdata.h b/engines/gnap/fontdata.h new file mode 100644 index 0000000000..9ad0d23ae8 --- /dev/null +++ b/engines/gnap/fontdata.h @@ -0,0 +1,851 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef GNAP_FONTDATA_H +#define GNAP_FONTDATA_H + +namespace Gnap { + +struct FONT_CHAR_INFO { +  const byte width;              // width, in bits (or pixels), of the character +  const uint16 offset;                // offset of the character's bitmap, in bytes, into the the FONT_INFO's data array +}; + +/*  +**  Font data for DejaVu Sans 9pt +*/ + +/* Character bitmaps for DejaVu Sans 9pt */ +const byte dejaVuSans9ptCharBitmaps[] =  +{ +	/* @0 ' ' (5 pixels wide) */ +	0x00, 0x00, /*                  */ +	0x00, 0x00, /*                  */ +	0x00, 0x00, /*                  */ +	0x00, 0x00, /*                  */ +	0x00, 0x00, /*                  */ + +	/* @10 '!' (1 pixels wide) */ +	0x1B, 0xF0, /*    ## ######     */ + +	/* @12 '"' (3 pixels wide) */ +	0x00, 0x70, /*          ###     */ +	0x00, 0x00, /*                  */ +	0x00, 0x70, /*          ###     */ + +	/* @18 '#' (8 pixels wide) */ +	0x04, 0x00, /*      #           */ +	0x14, 0x80, /*    # #  #        */ +	0x0F, 0x80, /*     #####        */ +	0x04, 0xE0, /*      #  ###      */ +	0x1C, 0x80, /*    ###  #        */ +	0x07, 0xC0, /*      #####       */ +	0x04, 0xA0, /*      #  # #      */ +	0x00, 0x80, /*         #        */ + +	/* @34 '$' (5 pixels wide) */ +	0x09, 0xC0, /*     #  ###       */ +	0x11, 0x20, /*    #   #  #      */ +	0x7F, 0xF0, /*  ###########     */ +	0x12, 0x20, /*    #  #   #      */ +	0x0E, 0x40, /*     ###  #       */ + +	/* @44 '%' (10 pixels wide) */ +	0x00, 0xE0, /*         ###      */ +	0x01, 0x10, /*        #   #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x0C, 0xE0, /*     ##  ###      */ +	0x03, 0x00, /*       ##         */ +	0x01, 0x80, /*        ##        */ +	0x0E, 0x60, /*     ###  ##      */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x00, /*    #   #         */ +	0x0E, 0x00, /*     ###          */ + +	/* @64 '&' (8 pixels wide) */ +	0x0E, 0x00, /*     ###          */ +	0x19, 0xE0, /*    ##  ####      */ +	0x10, 0x90, /*    #    #  #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x12, 0x20, /*    #  #   #      */ +	0x0C, 0x00, /*     ##           */ +	0x14, 0x00, /*    # #           */ +	0x13, 0x00, /*    #  ##         */ + +	/* @80 ''' (1 pixels wide) */ +	0x00, 0x70, /*          ###     */ + +	/* @82 '(' (3 pixels wide) */ +	0x07, 0xC0, /*      #####       */ +	0x38, 0x38, /*   ###     ###    */ +	0x20, 0x08, /*   #         #    */ + +	/* @88 ')' (3 pixels wide) */ +	0x20, 0x08, /*   #         #    */ +	0x38, 0x38, /*   ###     ###    */ +	0x07, 0xC0, /*      #####       */ + +	/* @94 '*' (5 pixels wide) */ +	0x01, 0x20, /*        #  #      */ +	0x00, 0xC0, /*         ##       */ +	0x03, 0xF0, /*       ######     */ +	0x00, 0xC0, /*         ##       */ +	0x01, 0x20, /*        #  #      */ + +	/* @104 '+' (7 pixels wide) */ +	0x02, 0x00, /*       #          */ +	0x02, 0x00, /*       #          */ +	0x02, 0x00, /*       #          */ +	0x1F, 0xC0, /*    #######       */ +	0x02, 0x00, /*       #          */ +	0x02, 0x00, /*       #          */ +	0x02, 0x00, /*       #          */ + +	/* @118 ',' (1 pixels wide) */ +	0x38, 0x00, /*   ###            */ + +	/* @120 '-' (3 pixels wide) */ +	0x02, 0x00, /*       #          */ +	0x02, 0x00, /*       #          */ +	0x02, 0x00, /*       #          */ + +	/* @126 '.' (1 pixels wide) */ +	0x18, 0x00, /*    ##            */ + +	/* @128 '/' (4 pixels wide) */ +	0x30, 0x00, /*   ##             */ +	0x0E, 0x00, /*     ###          */ +	0x01, 0xC0, /*        ###       */ +	0x00, 0x30, /*           ##     */ + +	/* @136 '0' (6 pixels wide) */ +	0x07, 0xC0, /*      #####       */ +	0x18, 0x30, /*    ##     ##     */ +	0x10, 0x10, /*    #       #     */ +	0x10, 0x10, /*    #       #     */ +	0x18, 0x30, /*    ##     ##     */ +	0x07, 0xC0, /*      #####       */ + +	/* @148 '1' (5 pixels wide) */ +	0x10, 0x10, /*    #       #     */ +	0x10, 0x10, /*    #       #     */ +	0x1F, 0xF0, /*    #########     */ +	0x10, 0x00, /*    #             */ +	0x10, 0x00, /*    #             */ + +	/* @158 '2' (6 pixels wide) */ +	0x10, 0x20, /*    #      #      */ +	0x18, 0x10, /*    ##      #     */ +	0x14, 0x10, /*    # #     #     */ +	0x12, 0x10, /*    #  #    #     */ +	0x11, 0x30, /*    #   #  ##     */ +	0x10, 0xE0, /*    #    ###      */ + +	/* @170 '3' (6 pixels wide) */ +	0x08, 0x20, /*     #     #      */ +	0x10, 0x10, /*    #       #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x0E, 0xE0, /*     ### ###      */ + +	/* @182 '4' (6 pixels wide) */ +	0x06, 0x00, /*      ##          */ +	0x05, 0x80, /*      # ##        */ +	0x04, 0x40, /*      #   #       */ +	0x04, 0x30, /*      #    ##     */ +	0x1F, 0xF0, /*    #########     */ +	0x04, 0x00, /*      #           */ + +	/* @194 '5' (6 pixels wide) */ +	0x08, 0xF0, /*     #   ####     */ +	0x10, 0x90, /*    #    #  #     */ +	0x10, 0x90, /*    #    #  #     */ +	0x10, 0x90, /*    #    #  #     */ +	0x19, 0x90, /*    ##  ##  #     */ +	0x0F, 0x00, /*     ####         */ + +	/* @206 '6' (6 pixels wide) */ +	0x07, 0xC0, /*      #####       */ +	0x19, 0x20, /*    ##  #  #      */ +	0x10, 0x90, /*    #    #  #     */ +	0x10, 0x90, /*    #    #  #     */ +	0x19, 0x90, /*    ##  ##  #     */ +	0x0F, 0x20, /*     ####  #      */ + +	/* @218 '7' (6 pixels wide) */ +	0x00, 0x10, /*            #     */ +	0x10, 0x10, /*    #       #     */ +	0x0C, 0x10, /*     ##     #     */ +	0x03, 0x10, /*       ##   #     */ +	0x00, 0xD0, /*         ## #     */ +	0x00, 0x30, /*           ##     */ + +	/* @230 '8' (6 pixels wide) */ +	0x0E, 0xE0, /*     ### ###      */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x0E, 0xE0, /*     ### ###      */ + +	/* @242 '9' (6 pixels wide) */ +	0x09, 0xE0, /*     #  ####      */ +	0x13, 0x30, /*    #  ##  ##     */ +	0x12, 0x10, /*    #  #    #     */ +	0x12, 0x10, /*    #  #    #     */ +	0x09, 0x30, /*     #  #  ##     */ +	0x07, 0xC0, /*      #####       */ + +	/* @254 ':' (1 pixels wide) */ +	0x19, 0x80, /*    ##  ##        */ + +	/* @256 ';' (1 pixels wide) */ +	0x39, 0x80, /*   ###  ##        */ + +	/* @258 '<' (8 pixels wide) */ +	0x03, 0x00, /*       ##         */ +	0x03, 0x00, /*       ##         */ +	0x03, 0x00, /*       ##         */ +	0x04, 0x80, /*      #  #        */ +	0x04, 0x80, /*      #  #        */ +	0x04, 0x80, /*      #  #        */ +	0x0C, 0xC0, /*     ##  ##       */ +	0x08, 0x40, /*     #    #       */ + +	/* @274 '=' (8 pixels wide) */ +	0x05, 0x00, /*      # #         */ +	0x05, 0x00, /*      # #         */ +	0x05, 0x00, /*      # #         */ +	0x05, 0x00, /*      # #         */ +	0x05, 0x00, /*      # #         */ +	0x05, 0x00, /*      # #         */ +	0x05, 0x00, /*      # #         */ +	0x05, 0x00, /*      # #         */ + +	/* @290 '>' (8 pixels wide) */ +	0x08, 0x40, /*     #    #       */ +	0x0C, 0xC0, /*     ##  ##       */ +	0x04, 0x80, /*      #  #        */ +	0x04, 0x80, /*      #  #        */ +	0x04, 0x80, /*      #  #        */ +	0x03, 0x00, /*       ##         */ +	0x03, 0x00, /*       ##         */ +	0x03, 0x00, /*       ##         */ + +	/* @306 '?' (5 pixels wide) */ +	0x00, 0x20, /*           #      */ +	0x00, 0x10, /*            #     */ +	0x1B, 0x10, /*    ## ##   #     */ +	0x00, 0x90, /*         #  #     */ +	0x00, 0x60, /*          ##      */ + +	/* @316 '@' (11 pixels wide) */ +	0x0F, 0x80, /*     #####        */ +	0x10, 0x40, /*    #     #       */ +	0x20, 0x20, /*   #       #      */ +	0x47, 0x10, /*  #   ###   #     */ +	0x48, 0x90, /*  #  #   #  #     */ +	0x48, 0x90, /*  #  #   #  #     */ +	0x48, 0x90, /*  #  #   #  #     */ +	0x4F, 0x90, /*  #  #####  #     */ +	0x28, 0x20, /*   # #     #      */ +	0x04, 0x60, /*      #   ##      */ +	0x03, 0x80, /*       ###        */ + +	/* @338 'A' (8 pixels wide) */ +	0x10, 0x00, /*    #             */ +	0x0E, 0x00, /*     ###          */ +	0x05, 0xC0, /*      # ###       */ +	0x04, 0x30, /*      #    ##     */ +	0x04, 0x30, /*      #    ##     */ +	0x05, 0xC0, /*      # ###       */ +	0x0E, 0x00, /*     ###          */ +	0x10, 0x00, /*    #             */ + +	/* @354 'B' (6 pixels wide) */ +	0x1F, 0xF0, /*    #########     */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x0E, 0xE0, /*     ### ###      */ + +	/* @366 'C' (6 pixels wide) */ +	0x07, 0xC0, /*      #####       */ +	0x08, 0x20, /*     #     #      */ +	0x10, 0x10, /*    #       #     */ +	0x10, 0x10, /*    #       #     */ +	0x10, 0x10, /*    #       #     */ +	0x08, 0x20, /*     #     #      */ + +	/* @378 'D' (7 pixels wide) */ +	0x1F, 0xF0, /*    #########     */ +	0x10, 0x10, /*    #       #     */ +	0x10, 0x10, /*    #       #     */ +	0x10, 0x10, /*    #       #     */ +	0x10, 0x10, /*    #       #     */ +	0x08, 0x20, /*     #     #      */ +	0x07, 0xC0, /*      #####       */ + +	/* @392 'E' (6 pixels wide) */ +	0x1F, 0xF0, /*    #########     */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x10, /*    #   #   #     */ + +	/* @404 'F' (5 pixels wide) */ +	0x1F, 0xF0, /*    #########     */ +	0x01, 0x10, /*        #   #     */ +	0x01, 0x10, /*        #   #     */ +	0x01, 0x10, /*        #   #     */ +	0x01, 0x10, /*        #   #     */ + +	/* @414 'G' (7 pixels wide) */ +	0x07, 0xC0, /*      #####       */ +	0x08, 0x20, /*     #     #      */ +	0x10, 0x10, /*    #       #     */ +	0x10, 0x10, /*    #       #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x0F, 0x20, /*     ####  #      */ + +	/* @428 'H' (7 pixels wide) */ +	0x1F, 0xF0, /*    #########     */ +	0x01, 0x00, /*        #         */ +	0x01, 0x00, /*        #         */ +	0x01, 0x00, /*        #         */ +	0x01, 0x00, /*        #         */ +	0x01, 0x00, /*        #         */ +	0x1F, 0xF0, /*    #########     */ + +	/* @442 'I' (1 pixels wide) */ +	0x1F, 0xF0, /*    #########     */ + +	/* @444 'J' (3 pixels wide) */ +	0x40, 0x00, /*  #               */ +	0x40, 0x00, /*  #               */ +	0x3F, 0xF0, /*   ##########     */ + +	/* @450 'K' (6 pixels wide) */ +	0x1F, 0xF0, /*    #########     */ +	0x01, 0x00, /*        #         */ +	0x02, 0x80, /*       # #        */ +	0x04, 0x40, /*      #   #       */ +	0x08, 0x20, /*     #     #      */ +	0x10, 0x10, /*    #       #     */ + +	/* @462 'L' (5 pixels wide) */ +	0x1F, 0xF0, /*    #########     */ +	0x10, 0x00, /*    #             */ +	0x10, 0x00, /*    #             */ +	0x10, 0x00, /*    #             */ +	0x10, 0x00, /*    #             */ + +	/* @472 'M' (8 pixels wide) */ +	0x1F, 0xF0, /*    #########     */ +	0x00, 0x60, /*          ##      */ +	0x01, 0x80, /*        ##        */ +	0x06, 0x00, /*      ##          */ +	0x06, 0x00, /*      ##          */ +	0x01, 0x80, /*        ##        */ +	0x00, 0x60, /*          ##      */ +	0x1F, 0xF0, /*    #########     */ + +	/* @488 'N' (7 pixels wide) */ +	0x1F, 0xF0, /*    #########     */ +	0x00, 0x30, /*           ##     */ +	0x00, 0xC0, /*         ##       */ +	0x01, 0x00, /*        #         */ +	0x06, 0x00, /*      ##          */ +	0x18, 0x00, /*    ##            */ +	0x1F, 0xF0, /*    #########     */ + +	/* @502 'O' (7 pixels wide) */ +	0x07, 0xC0, /*      #####       */ +	0x08, 0x20, /*     #     #      */ +	0x10, 0x10, /*    #       #     */ +	0x10, 0x10, /*    #       #     */ +	0x10, 0x10, /*    #       #     */ +	0x08, 0x20, /*     #     #      */ +	0x07, 0xC0, /*      #####       */ + +	/* @516 'P' (6 pixels wide) */ +	0x1F, 0xF0, /*    #########     */ +	0x01, 0x10, /*        #   #     */ +	0x01, 0x10, /*        #   #     */ +	0x01, 0x10, /*        #   #     */ +	0x01, 0x10, /*        #   #     */ +	0x00, 0xE0, /*         ###      */ + +	/* @528 'Q' (7 pixels wide) */ +	0x07, 0xC0, /*      #####       */ +	0x08, 0x20, /*     #     #      */ +	0x10, 0x10, /*    #       #     */ +	0x10, 0x10, /*    #       #     */ +	0x30, 0x10, /*   ##       #     */ +	0x48, 0x20, /*  #  #     #      */ +	0x07, 0xC0, /*      #####       */ + +	/* @542 'R' (7 pixels wide) */ +	0x1F, 0xF0, /*    #########     */ +	0x01, 0x10, /*        #   #     */ +	0x01, 0x10, /*        #   #     */ +	0x01, 0x10, /*        #   #     */ +	0x03, 0x10, /*       ##   #     */ +	0x0C, 0xE0, /*     ##  ###      */ +	0x10, 0x00, /*    #             */ + +	/* @556 'S' (6 pixels wide) */ +	0x08, 0xE0, /*     #   ###      */ +	0x11, 0x90, /*    #   ##  #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x0E, 0x20, /*     ###   #      */ + +	/* @568 'T' (7 pixels wide) */ +	0x00, 0x10, /*            #     */ +	0x00, 0x10, /*            #     */ +	0x00, 0x10, /*            #     */ +	0x1F, 0xF0, /*    #########     */ +	0x00, 0x10, /*            #     */ +	0x00, 0x10, /*            #     */ +	0x00, 0x10, /*            #     */ + +	/* @582 'U' (7 pixels wide) */ +	0x0F, 0xF0, /*     ########     */ +	0x18, 0x00, /*    ##            */ +	0x10, 0x00, /*    #             */ +	0x10, 0x00, /*    #             */ +	0x10, 0x00, /*    #             */ +	0x18, 0x00, /*    ##            */ +	0x0F, 0xF0, /*     ########     */ + +	/* @596 'V' (8 pixels wide) */ +	0x00, 0x30, /*           ##     */ +	0x01, 0xC0, /*        ###       */ +	0x06, 0x00, /*      ##          */ +	0x18, 0x00, /*    ##            */ +	0x18, 0x00, /*    ##            */ +	0x06, 0x00, /*      ##          */ +	0x01, 0xC0, /*        ###       */ +	0x00, 0x30, /*           ##     */ + +	/* @612 'W' (11 pixels wide) */ +	0x00, 0x10, /*            #     */ +	0x00, 0xE0, /*         ###      */ +	0x07, 0x00, /*      ###         */ +	0x18, 0x00, /*    ##            */ +	0x07, 0x80, /*      ####        */ +	0x00, 0x70, /*          ###     */ +	0x07, 0x80, /*      ####        */ +	0x18, 0x00, /*    ##            */ +	0x07, 0x00, /*      ###         */ +	0x00, 0xE0, /*         ###      */ +	0x00, 0x10, /*            #     */ + +	/* @634 'X' (7 pixels wide) */ +	0x10, 0x10, /*    #       #     */ +	0x08, 0x30, /*     #     ##     */ +	0x06, 0xC0, /*      ## ##       */ +	0x01, 0x00, /*        #         */ +	0x06, 0xC0, /*      ## ##       */ +	0x08, 0x30, /*     #     ##     */ +	0x10, 0x10, /*    #       #     */ + +	/* @648 'Y' (7 pixels wide) */ +	0x00, 0x10, /*            #     */ +	0x00, 0x60, /*          ##      */ +	0x01, 0x80, /*        ##        */ +	0x1E, 0x00, /*    ####          */ +	0x01, 0x80, /*        ##        */ +	0x00, 0x60, /*          ##      */ +	0x00, 0x10, /*            #     */ + +	/* @662 'Z' (7 pixels wide) */ +	0x18, 0x10, /*    ##      #     */ +	0x14, 0x10, /*    # #     #     */ +	0x12, 0x10, /*    #  #    #     */ +	0x11, 0x10, /*    #   #   #     */ +	0x10, 0x90, /*    #    #  #     */ +	0x10, 0x50, /*    #     # #     */ +	0x10, 0x30, /*    #      ##     */ + +	/* @676 '[' (2 pixels wide) */ +	0x7F, 0xF0, /*  ###########     */ +	0x40, 0x10, /*  #         #     */ + +	/* @680 '\' (4 pixels wide) */ +	0x00, 0x30, /*           ##     */ +	0x01, 0xC0, /*        ###       */ +	0x0E, 0x00, /*     ###          */ +	0x30, 0x00, /*   ##             */ + +	/* @688 ']' (2 pixels wide) */ +	0x40, 0x10, /*  #         #     */ +	0x7F, 0xF0, /*  ###########     */ + +	/* @692 '^' (6 pixels wide) */ +	0x00, 0x40, /*          #       */ +	0x00, 0x20, /*           #      */ +	0x00, 0x10, /*            #     */ +	0x00, 0x10, /*            #     */ +	0x00, 0x20, /*           #      */ +	0x00, 0x40, /*          #       */ + +	/* @704 '_' (6 pixels wide) */ +	0x80, 0x00, /* #                */ +	0x80, 0x00, /* #                */ +	0x80, 0x00, /* #                */ +	0x80, 0x00, /* #                */ +	0x80, 0x00, /* #                */ +	0x80, 0x00, /* #                */ + +	/* @716 '`' (2 pixels wide) */ +	0x00, 0x08, /*             #    */ +	0x00, 0x10, /*            #     */ + +	/* @720 'a' (6 pixels wide) */ +	0x0C, 0x80, /*     ##  #        */ +	0x12, 0x40, /*    #  #  #       */ +	0x12, 0x40, /*    #  #  #       */ +	0x12, 0x40, /*    #  #  #       */ +	0x0A, 0x40, /*     # #  #       */ +	0x1F, 0x80, /*    ######        */ + +	/* @732 'b' (6 pixels wide) */ +	0x1F, 0xF8, /*    ##########    */ +	0x18, 0xC0, /*    ##   ##       */ +	0x10, 0x40, /*    #     #       */ +	0x10, 0x40, /*    #     #       */ +	0x18, 0xC0, /*    ##   ##       */ +	0x0F, 0x80, /*     #####        */ + +	/* @744 'c' (5 pixels wide) */ +	0x0F, 0x80, /*     #####        */ +	0x18, 0xC0, /*    ##   ##       */ +	0x10, 0x40, /*    #     #       */ +	0x10, 0x40, /*    #     #       */ +	0x08, 0x80, /*     #   #        */ + +	/* @754 'd' (6 pixels wide) */ +	0x0F, 0x80, /*     #####        */ +	0x18, 0xC0, /*    ##   ##       */ +	0x10, 0x40, /*    #     #       */ +	0x10, 0x40, /*    #     #       */ +	0x18, 0xC0, /*    ##   ##       */ +	0x1F, 0xF8, /*    ##########    */ + +	/* @766 'e' (6 pixels wide) */ +	0x0F, 0x80, /*     #####        */ +	0x0A, 0xC0, /*     # # ##       */ +	0x12, 0x40, /*    #  #  #       */ +	0x12, 0x40, /*    #  #  #       */ +	0x12, 0xC0, /*    #  # ##       */ +	0x0B, 0x80, /*     # ###        */ + +	/* @778 'f' (4 pixels wide) */ +	0x00, 0x40, /*          #       */ +	0x1F, 0xF0, /*    #########     */ +	0x00, 0x48, /*          #  #    */ +	0x00, 0x48, /*          #  #    */ + +	/* @786 'g' (6 pixels wide) */ +	0x0F, 0x80, /*     #####        */ +	0x58, 0xC0, /*  # ##   ##       */ +	0x90, 0x40, /* #  #     #       */ +	0x90, 0x40, /* #  #     #       */ +	0xD8, 0xC0, /* ## ##   ##       */ +	0x7F, 0xC0, /*  #########       */ + +	/* @798 'h' (6 pixels wide) */ +	0x1F, 0xF8, /*    ##########    */ +	0x00, 0x80, /*         #        */ +	0x00, 0x40, /*          #       */ +	0x00, 0x40, /*          #       */ +	0x00, 0x40, /*          #       */ +	0x1F, 0x80, /*    ######        */ + +	/* @810 'i' (1 pixels wide) */ +	0x1F, 0xD0, /*    ####### #     */ + +	/* @812 'j' (2 pixels wide) */ +	0x80, 0x00, /* #                */ +	0xFF, 0xD0, /* ########## #     */ + +	/* @816 'k' (5 pixels wide) */ +	0x1F, 0xF8, /*    ##########    */ +	0x02, 0x00, /*       #          */ +	0x05, 0x00, /*      # #         */ +	0x08, 0x80, /*     #   #        */ +	0x10, 0x40, /*    #     #       */ + +	/* @826 'l' (1 pixels wide) */ +	0x1F, 0xF8, /*    ##########    */ + +	/* @828 'm' (9 pixels wide) */ +	0x1F, 0xC0, /*    #######       */ +	0x00, 0x40, /*          #       */ +	0x00, 0x40, /*          #       */ +	0x00, 0x40, /*          #       */ +	0x1F, 0x80, /*    ######        */ +	0x00, 0x40, /*          #       */ +	0x00, 0x40, /*          #       */ +	0x00, 0x40, /*          #       */ +	0x1F, 0x80, /*    ######        */ + +	/* @846 'n' (6 pixels wide) */ +	0x1F, 0xC0, /*    #######       */ +	0x00, 0x80, /*         #        */ +	0x00, 0x40, /*          #       */ +	0x00, 0x40, /*          #       */ +	0x00, 0x40, /*          #       */ +	0x1F, 0x80, /*    ######        */ + +	/* @858 'o' (6 pixels wide) */ +	0x0F, 0x80, /*     #####        */ +	0x18, 0xC0, /*    ##   ##       */ +	0x10, 0x40, /*    #     #       */ +	0x10, 0x40, /*    #     #       */ +	0x18, 0xC0, /*    ##   ##       */ +	0x0F, 0x80, /*     #####        */ + +	/* @870 'p' (6 pixels wide) */ +	0xFF, 0xC0, /* ##########       */ +	0x18, 0xC0, /*    ##   ##       */ +	0x10, 0x40, /*    #     #       */ +	0x10, 0x40, /*    #     #       */ +	0x18, 0xC0, /*    ##   ##       */ +	0x0F, 0x80, /*     #####        */ + +	/* @882 'q' (6 pixels wide) */ +	0x0F, 0x80, /*     #####        */ +	0x18, 0xC0, /*    ##   ##       */ +	0x10, 0x40, /*    #     #       */ +	0x10, 0x40, /*    #     #       */ +	0x18, 0xC0, /*    ##   ##       */ +	0xFF, 0xC0, /* ##########       */ + +	/* @894 'r' (4 pixels wide) */ +	0x1F, 0xC0, /*    #######       */ +	0x00, 0x80, /*         #        */ +	0x00, 0x40, /*          #       */ +	0x00, 0x40, /*          #       */ + +	/* @902 's' (5 pixels wide) */ +	0x09, 0x80, /*     #  ##        */ +	0x12, 0x40, /*    #  #  #       */ +	0x12, 0x40, /*    #  #  #       */ +	0x12, 0x40, /*    #  #  #       */ +	0x0C, 0x80, /*     ##  #        */ + +	/* @912 't' (4 pixels wide) */ +	0x00, 0x40, /*          #       */ +	0x1F, 0xF0, /*    #########     */ +	0x10, 0x40, /*    #     #       */ +	0x10, 0x40, /*    #     #       */ + +	/* @920 'u' (6 pixels wide) */ +	0x0F, 0xC0, /*     ######       */ +	0x10, 0x00, /*    #             */ +	0x10, 0x00, /*    #             */ +	0x10, 0x00, /*    #             */ +	0x08, 0x00, /*     #            */ +	0x1F, 0xC0, /*    #######       */ + +	/* @932 'v' (6 pixels wide) */ +	0x00, 0xC0, /*         ##       */ +	0x07, 0x00, /*      ###         */ +	0x18, 0x00, /*    ##            */ +	0x18, 0x00, /*    ##            */ +	0x07, 0x00, /*      ###         */ +	0x00, 0xC0, /*         ##       */ + +	/* @944 'w' (9 pixels wide) */ +	0x00, 0xC0, /*         ##       */ +	0x07, 0x00, /*      ###         */ +	0x18, 0x00, /*    ##            */ +	0x07, 0x00, /*      ###         */ +	0x00, 0xC0, /*         ##       */ +	0x07, 0x00, /*      ###         */ +	0x18, 0x00, /*    ##            */ +	0x07, 0x00, /*      ###         */ +	0x00, 0xC0, /*         ##       */ + +	/* @962 'x' (6 pixels wide) */ +	0x10, 0x40, /*    #     #       */ +	0x0D, 0x80, /*     ## ##        */ +	0x02, 0x00, /*       #          */ +	0x02, 0x00, /*       #          */ +	0x0D, 0x80, /*     ## ##        */ +	0x10, 0x40, /*    #     #       */ + +	/* @974 'y' (6 pixels wide) */ +	0x80, 0xC0, /* #       ##       */ +	0x83, 0x00, /* #     ##         */ +	0x4C, 0x00, /*  #  ##           */ +	0x38, 0x00, /*   ###            */ +	0x07, 0x00, /*      ###         */ +	0x00, 0xC0, /*         ##       */ + +	/* @986 'z' (5 pixels wide) */ +	0x18, 0x40, /*    ##    #       */ +	0x14, 0x40, /*    # #   #       */ +	0x12, 0x40, /*    #  #  #       */ +	0x11, 0x40, /*    #   # #       */ +	0x10, 0xC0, /*    #    ##       */ + +	/* @996 '{' (5 pixels wide) */ +	0x02, 0x00, /*       #          */ +	0x02, 0x00, /*       #          */ +	0x7D, 0xF0, /*  ##### #####     */ +	0x40, 0x10, /*  #         #     */ +	0x40, 0x10, /*  #         #     */ + +	/* @1006 '|' (1 pixels wide) */ +	0xFF, 0xF0, /* ############     */ + +	/* @1008 '}' (5 pixels wide) */ +	0x40, 0x10, /*  #         #     */ +	0x40, 0x10, /*  #         #     */ +	0x7D, 0xF0, /*  ##### #####     */ +	0x02, 0x00, /*       #          */ +	0x02, 0x00, /*       #          */ + +	/* @1018 '~' (8 pixels wide) */ +	0x02, 0x00, /*       #          */ +	0x01, 0x00, /*        #         */ +	0x01, 0x00, /*        #         */ +	0x01, 0x00, /*        #         */ +	0x02, 0x00, /*       #          */ +	0x02, 0x00, /*       #          */ +	0x02, 0x00, /*       #          */ +	0x01, 0x00, /*        #         */ +}; + +/* Character descriptors for DejaVu Sans 9pt */ +/* { [Char width in bits], [Offset into dejaVuSans9ptCharBitmaps in bytes] } */ +const FONT_CHAR_INFO dejaVuSans9ptCharDescriptors[] = +{ +	{5, 0}, 		/*   */ +	{1, 10}, 		/* ! */ +	{3, 12}, 		/* " */ +	{8, 18}, 		/* # */ +	{5, 34}, 		/* $ */ +	{10, 44}, 		/* % */ +	{8, 64}, 		/* & */ +	{1, 80}, 		/* ' */ +	{3, 82}, 		/* ( */ +	{3, 88}, 		/* ) */ +	{5, 94}, 		/* * */ +	{7, 104}, 		/* + */ +	{1, 118}, 		/* , */ +	{3, 120}, 		/* - */ +	{1, 126}, 		/* . */ +	{4, 128}, 		/* / */ +	{6, 136}, 		/* 0 */ +	{5, 148}, 		/* 1 */ +	{6, 158}, 		/* 2 */ +	{6, 170}, 		/* 3 */ +	{6, 182}, 		/* 4 */ +	{6, 194}, 		/* 5 */ +	{6, 206}, 		/* 6 */ +	{6, 218}, 		/* 7 */ +	{6, 230}, 		/* 8 */ +	{6, 242}, 		/* 9 */ +	{1, 254}, 		/* : */ +	{1, 256}, 		/* ; */ +	{8, 258}, 		/* < */ +	{8, 274}, 		/* = */ +	{8, 290}, 		/* > */ +	{5, 306}, 		/* ? */ +	{11, 316}, 		/* @ */ +	{8, 338}, 		/* A */ +	{6, 354}, 		/* B */ +	{6, 366}, 		/* C */ +	{7, 378}, 		/* D */ +	{6, 392}, 		/* E */ +	{5, 404}, 		/* F */ +	{7, 414}, 		/* G */ +	{7, 428}, 		/* H */ +	{1, 442}, 		/* I */ +	{3, 444}, 		/* J */ +	{6, 450}, 		/* K */ +	{5, 462}, 		/* L */ +	{8, 472}, 		/* M */ +	{7, 488}, 		/* N */ +	{7, 502}, 		/* O */ +	{6, 516}, 		/* P */ +	{7, 528}, 		/* Q */ +	{7, 542}, 		/* R */ +	{6, 556}, 		/* S */ +	{7, 568}, 		/* T */ +	{7, 582}, 		/* U */ +	{8, 596}, 		/* V */ +	{11, 612}, 		/* W */ +	{7, 634}, 		/* X */ +	{7, 648}, 		/* Y */ +	{7, 662}, 		/* Z */ +	{2, 676}, 		/* [ */ +	{4, 680}, 		/* \ */ +	{2, 688}, 		/* ] */ +	{6, 692}, 		/* ^ */ +	{6, 704}, 		/* _ */ +	{2, 716}, 		/* ` */ +	{6, 720}, 		/* a */ +	{6, 732}, 		/* b */ +	{5, 744}, 		/* c */ +	{6, 754}, 		/* d */ +	{6, 766}, 		/* e */ +	{4, 778}, 		/* f */ +	{6, 786}, 		/* g */ +	{6, 798}, 		/* h */ +	{1, 810}, 		/* i */ +	{2, 812}, 		/* j */ +	{5, 816}, 		/* k */ +	{1, 826}, 		/* l */ +	{9, 828}, 		/* m */ +	{6, 846}, 		/* n */ +	{6, 858}, 		/* o */ +	{6, 870}, 		/* p */ +	{6, 882}, 		/* q */ +	{4, 894}, 		/* r */ +	{5, 902}, 		/* s */ +	{4, 912}, 		/* t */ +	{6, 920}, 		/* u */ +	{6, 932}, 		/* v */ +	{9, 944}, 		/* w */ +	{6, 962}, 		/* x */ +	{6, 974}, 		/* y */ +	{5, 986}, 		/* z */ +	{5, 996}, 		/* { */ +	{1, 1006}, 		/* | */ +	{5, 1008}, 		/* } */ +	{8, 1018}, 		/* ~ */ +}; + +} // End of namespace Gnap + +#endif // GNAP_RESOURCE_H diff --git a/engines/gnap/gamesys.cpp b/engines/gnap/gamesys.cpp new file mode 100644 index 0000000000..d6f8db8c7a --- /dev/null +++ b/engines/gnap/gamesys.cpp @@ -0,0 +1,1303 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gamesys.h" +#include "gnap/fontdata.h" +#include "graphics/fontman.h" +#include "graphics/font.h" +#include "graphics/decoders/bmp.h" + +namespace Gnap { + +void GfxItem::testUpdRect(const Common::Rect &updRect) { +	Common::Rect intersectingRect; +	if (!updFlag && prevFrame.spriteId != -1 && +		updRectsCount < 20 && intersectRect(intersectingRect, prevFrame.rect, updRect)) +		updRects[updRectsCount++] = intersectingRect; +} + +// GameSys + +GameSys::GameSys(GnapEngine *vm) +	: _vm(vm) { +	 +	_newSpriteDrawItemsCount = 0; +	_removeSequenceItemsCount = 0; +	_removeSpriteDrawItemsCount = 0; +	_grabSpriteId = -1; +	_grabSpriteChanged = false; +	_reqRemoveSequenceItem = false; +	_removeSequenceItemSequenceId = -1; +	_removeSequenceItemValue = 0; +	_gfxItemsCount = 0; +	_animationsCount = 0; +	_backgroundImageValue3 = 0; +	_backgroundImageValue1 = 0; +	_backgroundImageValue4 = 0; +	_backgroundImageValue2 = 0; +	_backgroundImageError = true; +	_gameSysClock = 0; +	_lastUpdateClock = 0; +	_backgroundSurface = 0; +	_frontSurface = 0; +	for (int i = 0; i < kMaxAnimations; ++i) { +		_animations[i].sequenceId = -1; +		_animations[i].id = 0; +		_animations[i].status = 0; +	} +	_screenRect = Common::Rect(0, 0, 800, 600); +} + +GameSys::~GameSys() { +} + +void GameSys::insertSequence(int sequenceId, int a2, int sequenceId2, int a4, int flags, int totalDuration, int16 x, int16 y) { +	debug(0, "GameSys::insertSequence() [%08X, %d] -> [%08X, %d] (%d, %d)", sequenceId, a2, sequenceId2, a4, x, y); +	Sequence sequence; +	SequenceResource *sequenceResource = _vm->_sequenceCache->get(sequenceId); +	sequenceResource->_sequenceId = sequenceId; +	sequence.sequenceId = sequenceId; +	sequence.id = a2 != -1 ? a2 : sequenceResource->_field_8; +	sequence.sequenceId2 = sequenceId2 != (int32)0x80000000 ? sequenceId2 : sequenceResource->_sequenceId2; +	sequence.id2 = a4 != -1 ? a4 : sequenceResource->_field_10; +	sequence.flags = flags != -1 ? flags : sequenceResource->_flags; +	sequence.totalDuration = totalDuration != -1 ? totalDuration : sequenceResource->_totalDuration; +	sequence.x = (x < 10000 && x > -10000) ? x : sequenceResource->_xOffs; +	sequence.y = (y < 10000 && y > -10000) ? y : sequenceResource->_yOffs; +	_fatSequenceItems.push_back(sequence); +} + +void GameSys::insertDirtyRect(const Common::Rect &rect) { +	_dirtyRects.push_back(rect); +} + +void GameSys::removeSequence(int sequenceId, int a2, int a3) { +	//WaitForSingleObject(removeSequence2Mutex, INFINITE); +	if (_removeSequenceItemsCount < kMaxSequenceItems) { +		_removeSequenceItems[_removeSequenceItemsCount].sequenceId = sequenceId; +		_removeSequenceItems[_removeSequenceItemsCount].id = a2; +		_removeSequenceItems[_removeSequenceItemsCount].a3 = a3; +		++_removeSequenceItemsCount; +		//ResetEvent(removeSequenceItemsEvent); +		//ReleaseMutex(removeSequence2Mutex); +		//WaitForSingleObject(removeSequenceItemsEvent, INFINITE); +	} +} + +void GameSys::invalidateGrabCursorSprite(int id, Common::Rect &rect, Graphics::Surface *surface1, Graphics::Surface *surface2) { +	//WaitForSingleObject(grabSpriteMutex, INFINITE); +	_grabSpriteId = id; +	_grabSpriteRect = rect; +	_grabSpriteSurface2 = surface2; +	_grabSpriteSurface1 = surface1; +	//ResetEvent(grabSpriteEvent); +	_grabSpriteChanged = true; +	//ReleaseMutex(grabSpriteMutex); +	//WaitForSingleObject(grabSpriteEvent, INFINITE); +} + +void GameSys::requestClear2(int a1) { +	_fatSequenceItems.clear(); +	_seqItems.clear(); +	for (int i = 0; i < _gfxItemsCount; ++i) { +		GfxItem *gfxItem = &_gfxItems[i]; +		gfxItem->sequenceId = -1; +		gfxItem->animation = 0; +		gfxItem->soundValue = 0; +		if (a1) { +			gfxItem->currFrame.duration = 0; +			gfxItem->currFrame.spriteId = -1; +			gfxItem->currFrame.soundId = -1; +			gfxItem->currFrame.unkValue = -1; +			gfxItem->updFlag = true; +		} else { +			gfxItem->updFlag = false; +		} +  	} +	_lastUpdateClock = 0; +	_gameSysClock = 0; +} + +void GameSys::requestClear1() { +	_gfxItemsCount = 0; +	_fatSequenceItems.clear(); +	_seqItems.clear(); +	_lastUpdateClock = 0; +	_gameSysClock = 0; +} + +void GameSys::requestRemoveSequence(int sequenceId, int a2) { +	//WaitForSingleObject(removeSequence2Mutex, INFINITE); +	_reqRemoveSequenceItem = true; +	_removeSequenceItemSequenceId = sequenceId; +	_removeSequenceItemValue = a2; +	 +	handleReqRemoveSequenceItem();//CHECKME? +	 +	//ResetEvent(reqClearEvent); +	//ReleaseMutex(removeSequence2Mutex); +	//WaitForSingleObject(reqClearEvent, INFINITE); +} + +void GameSys::waitForUpdate() { +	//ResetEvent(updateEvent); +	//WaitForSingleObject(updateEvent, INFINITE); +} + +int GameSys::isSequenceActive(int sequenceId, int a2) { +	for (uint i = 0; i < _seqItems.size(); ++i) +		if (_seqItems[i].sequenceId == sequenceId && _seqItems[i].id == a2) +			return true; +	return false; +} + +void GameSys::setBackgroundSurface(Graphics::Surface *surface, int a4, int a5, int a6, int a7) { + +	debug(1, "GameSys::setBackgroundSurface() Setting background image"); +	 +	_backgroundSurface = surface; +	if (!_backgroundSurface) { +		_backgroundImageError = true; +		return; +	} +	 +	if (!_frontSurface || _frontSurface->w != surface->w || _frontSurface->h != surface->h) { +		debug(1, "GameSys::setBackgroundSurface() Creating background working surface"); +		if (_frontSurface) +			_frontSurface->free(); +		delete _frontSurface; +		_frontSurface = new Graphics::Surface(); +		_frontSurface->create(surface->w, surface->h, surface->format); +	} + +	memcpy(_frontSurface->getPixels(), surface->getPixels(), surface->pitch * surface->h); + +	_vm->_system->copyRectToScreen(_frontSurface->getPixels(), _frontSurface->pitch, 0, 0, _frontSurface->w, _frontSurface->h); + +	_backgroundImageError = false; +	_backgroundImageValue1 = a4; +	_backgroundImageValue3 = a6; +	_backgroundImageValue2 = a5; +	_backgroundImageValue4 = a7; +	_lastUpdateClock = 0; +	_gameSysClock = 0; + +} + +void GameSys::setScaleValues(int a1, int a2, int a3, int a4) { +	_backgroundImageValue1 = a1; +	_backgroundImageValue3 = a3; +	_backgroundImageValue2 = a2; +	_backgroundImageValue4 = a4; +} + +void GameSys::insertSpriteDrawItem(Graphics::Surface *surface, int x, int y, int id) { +	if (surface && _newSpriteDrawItemsCount < kMaxSpriteDrawItems) { +		_newSpriteDrawItems[_newSpriteDrawItemsCount].id = id; +		_newSpriteDrawItems[_newSpriteDrawItemsCount].rect = Common::Rect(x, y, x + surface->w, y + surface->h); +		_newSpriteDrawItems[_newSpriteDrawItemsCount].surface = surface; +		++_newSpriteDrawItemsCount; +	} +} + +void GameSys::removeSpriteDrawItem(Graphics::Surface *surface, int a2) { +	if (surface && _removeSpriteDrawItemsCount < kMaxSpriteDrawItems) { +		_removeSpriteDrawItems[_removeSpriteDrawItemsCount].id = a2; +		_removeSpriteDrawItems[_removeSpriteDrawItemsCount].surface = surface; +		++_removeSpriteDrawItemsCount; +	} +} + +void GameSys::drawSpriteToBackground(int x, int y, int resourceId) { + +	SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId); +	uint32 *sourcePalette = spriteResource->_palette; +	byte *sourcePixels = spriteResource->_pixels; +	int spriteWidth = spriteResource->_width; +	int spriteHeight = spriteResource->_height; +	Common::Rect dstRect(0, 0, spriteWidth, spriteHeight); +	blitSprite32(_backgroundSurface, x, y, sourcePixels, spriteResource->_width, dstRect, sourcePalette, true);//spriteResource->_transparent != 0); +	_vm->_spriteCache->release(resourceId); + +	// Add dirty rect so the modified background is redrawn +	insertDirtyRect(Common::Rect(x, y, x + spriteWidth, y + spriteHeight)); +} + +Graphics::Surface *GameSys::allocSurface(int width, int height) { +	Graphics::Surface *surface = new Graphics::Surface(); +	surface->create(width, height, _backgroundSurface->format); +	surface->fillRect(Common::Rect(0, 0, surface->w, surface->h), 0xFFFF00FF); +	return surface; +} + +Graphics::Surface *GameSys::createSurface(int resourceId) { +	debug(0, "GameSys::createSurface() resourceId: %08X", resourceId); +	 +	SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId); +	Graphics::Surface *surface = allocSurface(spriteResource->_width, spriteResource->_height); +	_vm->_spriteCache->release(resourceId); +	 +	drawSpriteToSurface(surface, 0, 0, resourceId); + +	return surface; +} + +void GameSys::drawSpriteToSurface(Graphics::Surface *surface, int x, int y, int resourceId) { +	SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId); +	uint32 *sourcePalette = spriteResource->_palette; +	byte *sourcePixels = spriteResource->_pixels; +	Common::Rect dstRect(0, 0, spriteResource->_width, spriteResource->_height); +	blitSprite32(surface, x, y, sourcePixels, spriteResource->_width, dstRect, sourcePalette, true);//spriteResource->_transparent != 0); +	_vm->_spriteCache->release(resourceId); +} + +void GameSys::drawTextToSurface(Graphics::Surface *surface, int x, int y, byte r, byte g, byte b, const char *text) { + +	// NOTE Not that nice but will have to do for now +	 +	bool doDirty = false; + +	if (!surface) { +		surface = _backgroundSurface; +		doDirty = true; +	} +	 +	uint32 color = surface->format.RGBToColor(r, g, b); + +	for (const char *cp = text; *cp != 0; ++cp) { +		byte c = *cp; +		if (c < 32 || c > 127) +			c = (byte)'_'; +		c -= 32; +		int w = dejaVuSans9ptCharDescriptors[c].width; +		const byte *data = dejaVuSans9ptCharBitmaps + dejaVuSans9ptCharDescriptors[c].offset; +		for (int xc = 0; xc < w; ++xc) { +			for (int yc = 15; yc >= 0; --yc) { +				byte *dst = (byte*)surface->getBasePtr(x + xc, y + yc); +				if (data[1 - (yc >> 3)] & (1 << (yc & 7))) +					WRITE_LE_UINT32(dst, color); +			} +			data += 2; +		} +		x += w + 1; +	} +	 +	if (doDirty) { +		insertDirtyRect(Common::Rect(x, y, x + getTextWidth(text), y + 16)); +	} +	 +} + +int GameSys::getTextWidth(const char *text) { +	int width = 0; +	for (const char *cp = text; *cp != 0; ++cp) { +		byte c = *cp; +		if (c < 32 || c > 127) +			c = (byte)'_'; +		c -= 32; +		width += dejaVuSans9ptCharDescriptors[c].width + 1; +	} +	return width; +} + +void GameSys::fillSurface(Graphics::Surface *surface, int x, int y, int width, int height, byte r, byte g, byte b) { +	Common::Rect rect(x, y, x + width, y + height); +	if (!surface) { +		_backgroundSurface->fillRect(rect, _backgroundSurface->format.RGBToColor(r, g, b));  +		insertDirtyRect(rect); +	} else { +		surface->fillRect(rect, surface->format.RGBToColor(r, g, b));  +	} +} + +void GameSys::setAnimation(int sequenceId, int id, int animationIndex) { +	if (animationIndex < kMaxAnimations) { +		_animations[animationIndex].sequenceId = sequenceId; +		_animations[animationIndex].id = id; +		_animations[animationIndex].status = 0; +	} +} + +int GameSys::getAnimationStatus(int animationIndex) { +	int result = -1; +	if (animationIndex < kMaxAnimations) +		result = _animations[animationIndex].status; +	return result; +} + +int GameSys::getSpriteWidthById(int resourceId) { +	SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId); +	const int width = spriteResource->_width; +	_vm->_spriteCache->release(resourceId); +	return width; +} + +int GameSys::getSpriteHeightById(int resourceId) { +	SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId); +	const int height = spriteResource->_height; +	_vm->_spriteCache->release(resourceId); +	return height; +} + +Graphics::Surface *GameSys::loadBitmap(int resourceId) { +	debug("GameSys::loadBitmap() resourceId: %08X", resourceId); +	if (_vm->_dat->getResourceType(resourceId) != 1) +		return 0; +	byte *resourceData = _vm->_dat->loadResource(resourceId); +	uint32 resourceSize = _vm->_dat->getResourceSize(resourceId); +	Common::MemoryReadStream stream(resourceData, resourceSize, DisposeAfterUse::NO); +	Graphics::Surface *bmpSurface; +	Graphics::BitmapDecoder bmp; +	if (!bmp.loadStream(stream)) +		error("GameSys::loadBitmap() Could not load bitmap resource %08X", resourceId); +	bmpSurface = bmp.getSurface()->convertTo(_vm->_system->getScreenFormat()); +	delete[] resourceData; +	return bmpSurface; +} + +void GameSys::drawBitmap(int resourceId) { +	Graphics::Surface *bmpSurface = loadBitmap(resourceId); +	if (!bmpSurface || !_backgroundSurface) { +		debug("GameSys::drawBitmap() Error loading the bitmap"); +		return; +	} +	if (bmpSurface->format != _backgroundSurface->format || +		bmpSurface->w != _backgroundSurface->w || bmpSurface->h != _backgroundSurface->h) { +		debug("GameSys::drawBitmap() Different bitmap properties than current background"); +	} else { +		byte *src = (byte*)bmpSurface->getPixels(); +		byte *dst = (byte*)_backgroundSurface->getPixels(); +		const int pitch = bmpSurface->pitch; +		int height = bmpSurface->h; +		while (height--) { +			memcpy(dst, src, pitch); +			src += pitch; +			dst += pitch; +		} +	} +	bmpSurface->free(); +	delete bmpSurface;	 + +	insertDirtyRect(Common::Rect(0, 0, 800, 600)); +} + +Sequence *GameSys::seqFind(int sequenceId, int a2, int *outIndex) { +	for (uint i = 0; i < _seqItems.size(); ++i) +		if (_seqItems[i].sequenceId == sequenceId && _seqItems[i].id == a2) { +			if (outIndex) +				*outIndex = i; +			return &_seqItems[i]; +		} +	return 0; +} + +int GameSys::seqLocateGfx(int sequenceId, int id, int *outGfxIndex) { +	for (int i = 0; i < _gfxItemsCount; ++i) { +		GfxItem *gfxItem = &_gfxItems[i]; +		if (gfxItem->sequenceId == sequenceId && gfxItem->id == id) { +			if (outGfxIndex) +				*outGfxIndex = i; +			return gfxItem->sequenceId; +		} +		if (gfxItem->id > id) { +			if (outGfxIndex) +				*outGfxIndex = i; +			return 0; +		} +	} +	if (outGfxIndex) +		*outGfxIndex = _gfxItemsCount; +	return 0; +} + +void GameSys::seqInsertGfx(int index, int duration) { +	 +	Sequence *seqItem = &_seqItems[index]; +	SequenceResource *sequenceResource = _vm->_sequenceCache->get(seqItem->sequenceId);	 + +	if (sequenceResource->_animationsCount > 50 - _gfxItemsCount) +		return; + +	int gfxIndex; +	seqLocateGfx(seqItem->sequenceId, seqItem->id, &gfxIndex); +	 +	if (gfxIndex != _gfxItemsCount) +		memcpy(&_gfxItems[gfxIndex + sequenceResource->_animationsCount],	&_gfxItems[gfxIndex], sizeof(GfxItem) * (_gfxItemsCount - gfxIndex)); +	_gfxItemsCount += sequenceResource->_animationsCount; +	 +	for (int i = 0; i < sequenceResource->_animationsCount; ++i) { +		int totalDuration; +		GfxItem *gfxItem = &_gfxItems[i + gfxIndex]; +		SequenceAnimation *animation = &sequenceResource->_animations[i]; + +		debug(0, "GameSys::seqInsertGfx() seqItem->sequenceId: %08X", seqItem->sequenceId); + +		gfxItem->sequenceId = seqItem->sequenceId; +		gfxItem->id = seqItem->id; +		gfxItem->animation = animation; +		gfxItem->currFrameNum = 0; +		gfxItem->flags = 0; +		gfxItem->delayTicks = seqItem->totalDuration + animation->field_4; +		gfxItem->updFlag = false; +		gfxItem->updRectsCount = 0; +		gfxItem->prevFrame.duration = 0; +		gfxItem->prevFrame.spriteId = -1; +		gfxItem->prevFrame.soundId = -1; +		gfxItem->prevFrame.unkValue = -1; +		totalDuration = duration; +		if ((seqItem->flags & 4) && totalDuration > 0) { +			gfxItem->prevFrame.duration = 1; +			if (gfxItem->delayTicks <= totalDuration) +				gfxItem->delayTicks = 0; +			else +				gfxItem->delayTicks -= totalDuration + 1; +			gfxItem->updFlag = false; +		} else if (gfxItem->delayTicks <= totalDuration) { +			int j; +			totalDuration -= gfxItem->delayTicks; +			gfxItem->delayTicks = 0; +			for (j = gfxItem->currFrameNum; j < animation->framesCount && animation->frames[j].duration <= totalDuration; ++j) { +				if (animation->frames[j].soundId != -1) +					_soundIds.push_back((gfxItem->sequenceId & 0xFFFF0000) | animation->frames[j].soundId); +				totalDuration -= animation->frames[j].duration; +			} +			if (animation->framesCount > j) +				gfxItem->currFrame = animation->frames[j++]; +			else +				gfxItem->currFrame = animation->frames[j - 1]; +			if (gfxItem->currFrame.spriteId != -1 && (seqItem->x != 0 || seqItem->y != 0)) +				gfxItem->currFrame.rect.translate(seqItem->x, seqItem->y); +			// Update sprite scaling				 +			if ((seqItem->flags & 1) && gfxItem->currFrame.rect.bottom >= _backgroundImageValue1 && gfxItem->currFrame.rect.bottom <= _backgroundImageValue3) { +				int v2 = _backgroundImageValue2	+ (gfxItem->currFrame.rect.bottom - _backgroundImageValue1) * +					(_backgroundImageValue4 - _backgroundImageValue2) / +					(_backgroundImageValue3 - _backgroundImageValue1); +				gfxItem->currFrame.rect.top = gfxItem->currFrame.rect.bottom - v2 * (gfxItem->currFrame.rect.bottom - gfxItem->currFrame.rect.top) / 1000; +				gfxItem->currFrame.rect.right = v2 * (gfxItem->currFrame.rect.right - gfxItem->currFrame.rect.left) / 1000 + gfxItem->currFrame.rect.left; +				gfxItem->currFrame.isScaled = 1; +			} +			gfxItem->currFrame.duration -= totalDuration; +			if (gfxItem->currFrame.soundId != -1) +				_soundIds.push_back((gfxItem->sequenceId & 0xFFFF0000) | gfxItem->currFrame.soundId); +			gfxItem->currFrameNum = j; +			gfxItem->updFlag = true; +		} else { +			gfxItem->delayTicks -= totalDuration + 1; +			gfxItem->updFlag = false; +		} +	} + +	for (int k = 0; k < kMaxAnimations; ++k) { +		if (_animations[k].sequenceId != -1 && _animations[k].sequenceId == seqItem->sequenceId && _animations[k].id == seqItem->id) { +			_animations[k].status = 1; +			break; +		} +	} +	 +} + +void GameSys::seqRemoveGfx(int sequenceId, int id) { +	int gfxIndex; +	if (seqLocateGfx(sequenceId, id, &gfxIndex)) { +		GfxItem *gfxItem = &_gfxItems[gfxIndex]; +		while (gfxIndex < _gfxItemsCount && gfxItem->sequenceId == sequenceId && gfxItem->id == id) { +			if (gfxItem->prevFrame.spriteId == -1) { +				--_gfxItemsCount; +				if (gfxIndex != _gfxItemsCount) +					memcpy(&_gfxItems[gfxIndex], &_gfxItems[gfxIndex + 1], sizeof(GfxItem) * (_gfxItemsCount - gfxIndex)); +			} else { +				gfxItem->sequenceId = -1; +				gfxItem->animation = 0; +				gfxItem->currFrame.duration = 0; +				gfxItem->currFrame.spriteId = -1; +				gfxItem->currFrame.soundId = -1; +				gfxItem->currFrame.unkValue = -1; +				gfxItem->updFlag = true; +				++gfxIndex; +				gfxItem = &_gfxItems[gfxIndex]; +			} +		} +	} +} + +bool GameSys::updateSequenceDuration(int sequenceId, int id, int *outDuration) { +	bool found = false; +	int duration = 0x7FFFFFFF; +	for (int i = 0; i < _gfxItemsCount; ++i) { +		GfxItem *gfxItem = &_gfxItems[i]; +		if (gfxItem->sequenceId == sequenceId && gfxItem->id == id) { +			found = true; +			SequenceAnimation *animation = gfxItem->animation; +			if (animation) { +				if (gfxItem->currFrameNum < animation->framesCount) +					return false; +				if (gfxItem->updFlag) { +					if (gfxItem->currFrame.duration > 0) +						return false; +					if (-gfxItem->currFrame.duration < duration) +						duration = -gfxItem->currFrame.duration; +				} else { +					if (gfxItem->prevFrame.duration > 0) +						return false; +					if (-gfxItem->prevFrame.duration < duration) +						duration = -gfxItem->prevFrame.duration; +				} +			} +		} +	} +	if (found) +		*outDuration = duration; +	return found; +} + +void GameSys::updateAnimationsStatus(int sequenceId, int a2) { + +	Animation *foundAnimation = 0; +	for (int animationIndex = 0; animationIndex < kMaxAnimations; ++animationIndex) { +		Animation *animation = &_animations[animationIndex]; +		if (animation->sequenceId != -1 && animation->sequenceId == sequenceId && animation->id == a2) { +			foundAnimation = animation; +			break; +		} +	} +	 +	if (!foundAnimation) +		return; + +	bool foundSequence = false; +	for (int i = 0; i < _gfxItemsCount; ++i) { +		GfxItem *gfxItem = &_gfxItems[i]; +		SequenceAnimation *animation = gfxItem->animation; +		if (gfxItem->sequenceId == sequenceId && gfxItem->id == a2 && animation) { +			foundSequence = true; +			if (animation->framesCount > gfxItem->currFrameNum || +				(gfxItem->updFlag && gfxItem->currFrame.duration > 1) || +				gfxItem->prevFrame.duration > 1) +				foundSequence = false; +			break; +		} +	} + +	if (foundSequence) { +		foundAnimation->sequenceId = -1; +		foundAnimation->status = 2; +	} + +} + +void GameSys::restoreBackgroundRect(const Common::Rect &rect) { +	Common::Rect clipRect;	 +	if (!intersectRect(clipRect, rect, _screenRect)) +		return; +	byte *src = (byte*)_backgroundSurface->getBasePtr(clipRect.left, clipRect.top); +	byte *dst = (byte*)_frontSurface->getBasePtr(clipRect.left, clipRect.top); +	const int bytes = _backgroundSurface->format.bytesPerPixel * clipRect.width(); +	int height = clipRect.height(); +	while (height--) { +		memcpy(dst, src, bytes); +		src += _backgroundSurface->pitch; +		dst += _frontSurface->pitch; +	} +} + +void GameSys::blitSurface32(Graphics::Surface *destSurface, int x, int y, Graphics::Surface *sourceSurface, +	Common::Rect &sourceRect, bool transparent) { +	 +	const int sourcePitch = sourceSurface->pitch; +	byte *dst = (byte*)destSurface->getBasePtr(x, y); +	byte *src = (byte*)sourceSurface->getBasePtr(sourceRect.left, sourceRect.top); +	int width = sourceRect.width(); +	int height = sourceRect.height(); +	while (height--) { +		byte *rsrc = src;		 +		byte *rdst = dst; +		for (int xc = 0; xc < width; ++xc) { +			uint32 pixel = READ_LE_UINT32(rsrc); +			if (!transparent || pixel != 0xFFFF00FF) +				WRITE_LE_UINT32(rdst, pixel); +			rsrc += 4; +			rdst += 4; +		} +		dst += destSurface->pitch; +		src += sourcePitch; +	} +} + +void GameSys::blitSprite32(Graphics::Surface *destSurface, int x, int y, byte *sourcePixels, +	int sourceWidth, Common::Rect &sourceRect, uint32 *sourcePalette, bool transparent) { +	 +	const int sourcePitch = (sourceWidth + 3) & 0xFFFFFFFC; +	byte *dst = (byte*)destSurface->getBasePtr(x, y); +	byte *src = sourcePixels + sourceRect.left + sourcePitch * sourceRect.top; +	int width = sourceRect.width(); +	int height = sourceRect.height(); +	while (height--) { +		byte *rdst = dst;		 +		for (int xc = 0; xc < width; ++xc) { +			byte srcPixel = src[xc]; +			if (!transparent || srcPixel) { +				uint32 rgb = sourcePalette[srcPixel]; +				rdst[0] = rgb & 0x000000FF; +				rdst[1] = (rgb & 0x0000FF00) >> 8; +				rdst[2] = (rgb & 0x00FF0000) >> 16; +			} +			rdst += 4; +		} +		dst += destSurface->pitch; +		src += sourcePitch; +	} +} + +void GameSys::blitSpriteScaled32(Graphics::Surface *destSurface, Common::Rect &frameRect, +	Common::Rect &destRect, byte *sourcePixels, int sourceWidth, Common::Rect &sourceRect, uint32 *sourcePalette) { +	 +	if (frameRect.height() <= 0 || frameRect.width() <= 0) +		return; + +	const int ys = ((sourceRect.bottom - sourceRect.top - 1) << 16) / (frameRect.bottom - frameRect.top - 1); +	const int xs = ((sourceRect.right - sourceRect.left - 1) << 16) / (frameRect.right - frameRect.left - 1); +	const int destPitch = destSurface->pitch; +	const int sourcePitch = (sourceWidth + 3) & 0xFFFFFFFC; + +	if (!frameRect.equals(destRect)) { +		byte *dst = (byte*)destSurface->getBasePtr(destRect.left, destRect.top); +		byte *src = sourcePixels + sourcePitch * sourceRect.top + sourceRect.left; +		const int height = destRect.bottom - destRect.top; +		const int width = destRect.right - destRect.left; +		int yi = ys * (destRect.top - frameRect.top); +		byte *hsrc = src + sourcePitch * ((yi + 0x8000) >> 16); +		for (int i = 0; i < height; ++i) { +			byte *wdst = dst; +			int xi = xs * (destRect.left - frameRect.left); +			byte *wsrc = hsrc + ((xi + 0x8000) >> 16); +			for (int j = 0; j < width; ++j) { +				byte srcPixel = *wsrc; +				if (srcPixel) { +					uint32 rgb = sourcePalette[srcPixel]; +					wdst[0] = rgb & 0x000000FF; +					wdst[1] = (rgb & 0x0000FF00) >> 8; +					wdst[2] = (rgb & 0x00FF0000) >> 16; +				} +				wdst += 4; +				xi += xs; +				wsrc = hsrc + ((xi + 0x8000) >> 16); +			} +			dst += destPitch; +			yi += ys; +			hsrc = src + sourcePitch * ((yi + 0x8000) >> 16); +		} +	} else { +		byte *dst = (byte*)destSurface->getBasePtr(frameRect.left, frameRect.top); +		byte *src = sourcePixels + sourcePitch * sourceRect.top + sourceRect.left; +		const int height = frameRect.bottom - frameRect.top; +		const int width = frameRect.right - frameRect.left; +		byte *hsrc = sourcePixels + sourcePitch * sourceRect.top + sourceRect.left; +		int yi = 0; +		for (int i = 0; i < height; ++i) { +			byte *wdst = dst; +			byte *wsrc = hsrc; +			int xi = 0; +			for (int j = 0; j < width; ++j) { +				byte srcPixel = *wsrc; +				if (srcPixel) { +					uint32 rgb = sourcePalette[srcPixel]; +					wdst[0] = rgb & 0x000000FF; +					wdst[1] = (rgb & 0x0000FF00) >> 8; +					wdst[2] = (rgb & 0x00FF0000) >> 16; +				} +				wdst += 4; +				xi += xs; +				wsrc = hsrc + ((xi + 0x8000) >> 16); +			} +			dst += destPitch; +			yi += ys; +			hsrc = src + sourcePitch * ((yi + 0x8000) >> 16); +		} +	} + +} + +void GameSys::seqDrawStaticFrame(Graphics::Surface *surface, SequenceFrame &frame, Common::Rect *subRect) { +	debug(1, "GameSys::seqDrawStaticFrame() rect: (%d, %d, %d, %d)", +		frame.rect.left, frame.rect.top, frame.rect.right, frame.rect.bottom); +	 +	Common::Rect srcRect = subRect ? *subRect : frame.rect; +	Common::Rect clipRect; +	 +	if (!intersectRect(clipRect, srcRect, _screenRect)) { +		debug(1, "GameSys::seqDrawStaticFrame() Surface not inside screen"); +		return; +	} + +	const int x = clipRect.left, y = clipRect.top; +	 +	clipRect.translate(-frame.rect.left, -frame.rect.top); + +	// TODO Save transparent flag somewhere +	blitSurface32(_frontSurface, x, y, surface, clipRect, true); + +} + +void GameSys::seqDrawSpriteFrame(SpriteResource *spriteResource, SequenceFrame &frame, Common::Rect *subRect) { +	debug(1, "GameSys::seqDrawSpriteFrame() spriteId: %04X; rect: (%d, %d, %d, %d)", +		frame.spriteId, frame.rect.left, frame.rect.top, frame.rect.right, frame.rect.bottom); +	 +	Common::Rect srcRect = subRect ? *subRect : frame.rect; +	Common::Rect clipRect; +	 +	if (!intersectRect(clipRect, srcRect, _screenRect)) { +		debug(1, "GameSys::seqDrawSpriteFrame() Sprite not inside screen"); +		return; +	} + +	uint32 *sourcePalette = spriteResource->_palette; +	byte *sourcePixels = spriteResource->_pixels; + +	const int x = clipRect.left, y = clipRect.top; +	 +	debug(1, "GameSys::seqDrawSpriteFrame() destX: %d; destY: %d; frame.isScaled: %d", x, y, frame.isScaled); + +	// 32bit sprite drawing +	if (frame.isScaled) { +		Common::Rect sourceRect(0, 0, spriteResource->_width, spriteResource->_height); +		blitSpriteScaled32(_frontSurface,	frame.rect, clipRect, sourcePixels, spriteResource->_width, sourceRect, sourcePalette); +	} else { +		clipRect.translate(-frame.rect.left, -frame.rect.top); +		blitSprite32(_frontSurface, x, y, sourcePixels, spriteResource->_width, clipRect, sourcePalette, true);//spriteResource->_transparent != 0); +	} + +} + +void GameSys::drawSprites() { + +	debug(1, "GameSys::drawSprites() _gfxItemsCount: %d", _gfxItemsCount); + +	// TODO Split into multiple functions for clarity + +	// Restore dirty background and collect rects to be redrawn for all sprites  +	// which aren't marked to be redrawn yet +	Common::Rect intersectingRect; +	for (uint i = 0; i < _dirtyRects.size(); ++i) { +		restoreBackgroundRect(_dirtyRects[i]); +		for (int j = 0; j < _gfxItemsCount; ++j) +			_gfxItems[j].testUpdRect(_dirtyRects[i]); +	} +	 +	for (int k = 0; k < _gfxItemsCount; ++k) { +		GfxItem *gfxItem2 = &_gfxItems[k]; + +		if (!gfxItem2->updFlag) +			continue; + +		if (gfxItem2->prevFrame.spriteId != -1) { +			int transparent = 0; +			if (gfxItem2->currFrame.spriteId != -1 && !(gfxItem2->flags & 2)) { +				if (gfxItem2->flags & 1) { +					transparent = 1; +				} else { +					int resourceId = (gfxItem2->sequenceId & 0xFFFF0000) | gfxItem2->currFrame.spriteId; +					SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId); +					transparent = spriteResource->_transparent; +					_vm->_spriteCache->release(resourceId); +				} +			} +			if ((gfxItem2->flags & 8) || gfxItem2->currFrame.spriteId == -1 || +				(!(gfxItem2->flags & 2) && (!gfxItem2->prevFrame.rect.equals(gfxItem2->currFrame.rect) || !transparent))) { +				restoreBackgroundRect(gfxItem2->prevFrame.rect); +				for (int l = 0; l < _gfxItemsCount; ++l) +					_gfxItems[l].testUpdRect(gfxItem2->prevFrame.rect); +			} +		} + +		if (gfxItem2->currFrame.spriteId != -1) { +			int transparent = 0; +			if (gfxItem2->flags & 1) { +				transparent = 1; +			} else if (!(gfxItem2->flags & 2)) { +				int resourceId = (gfxItem2->sequenceId & 0xFFFF0000) | gfxItem2->currFrame.spriteId; +				SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId); +				transparent = spriteResource->_transparent; +				_vm->_spriteCache->release(resourceId); +			} +			if (((gfxItem2->flags & 2) && !(gfxItem2->flags & 8)) || +				gfxItem2->prevFrame.spriteId == -1 || +				!gfxItem2->prevFrame.rect.equals(gfxItem2->currFrame.rect) || transparent) { +				for (int l = k; l < _gfxItemsCount; ++l) +					_gfxItems[l].testUpdRect(gfxItem2->currFrame.rect); +			} +		} + +	} + +	for (int m = 0; m < _gfxItemsCount; ++m) { +		GfxItem *gfxItem5 = &_gfxItems[m]; +		 +		debug(0, "DrawGfxItem(%d) updFlag: %d; currFrame.spriteId: %04X; updRectsCount: %d; flags: %04X; sequenceId: %08X", +			m, gfxItem5->updFlag, gfxItem5->currFrame.spriteId, gfxItem5->updRectsCount, gfxItem5->flags, gfxItem5->sequenceId); +		 +		if (gfxItem5->updFlag) { +			if (gfxItem5->currFrame.spriteId != -1) { +				if (gfxItem5->flags & 1) { +					seqDrawStaticFrame(gfxItem5->surface, gfxItem5->currFrame, 0); +					//debug("seqDrawStaticFrame"); +				} else if (gfxItem5->flags & 2) { +					// TODO seqDrawAviFrame(gfxItem5->currFrame.spriteId, &gfxItem5->currFrame, 0, gfxItem5->flags & 8); +				} else { +					int resourceId = (gfxItem5->sequenceId & 0xFFFF0000) | gfxItem5->currFrame.spriteId; +					SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId); +					seqDrawSpriteFrame(spriteResource, gfxItem5->currFrame, 0); +					_vm->_spriteCache->release(resourceId); +				} +			} +		} else if (gfxItem5->updRectsCount > 0) { +			if (gfxItem5->flags & 1) { +				for (int n = 0; n < gfxItem5->updRectsCount; ++n) +					seqDrawStaticFrame(gfxItem5->surface, gfxItem5->prevFrame, &gfxItem5->updRects[n]); +			} else if (gfxItem5->flags & 2) { +				/* TODO +				spriteData4 = gfxItem5->prevFrame.spriteId; +				for (int n = 0; n < gfxItem5->updRectsCount; ++n) +					seqDrawAviFrame(spriteData4, &gfxItem5->prevFrame, &gfxItem5->updRects[n], gfxItem5->flags & 8); +				*/ +			} else { +				int resourceId = (gfxItem5->sequenceId & 0xFFFF0000) | gfxItem5->prevFrame.spriteId; +				SpriteResource *spriteResource = _vm->_spriteCache->get(resourceId); +				for (int n = 0; n < gfxItem5->updRectsCount; ++n) +					seqDrawSpriteFrame(spriteResource, gfxItem5->prevFrame, &gfxItem5->updRects[n]); +				_vm->_spriteCache->release(resourceId); +			} +		} +	} + +	debug(1, "GameSys::drawSprites() OK"); + +} + +void GameSys::updateRect(const Common::Rect &r) { +	debug(1, "GameSys::updateRect() %d, %d, %d, %d [%d, %d]", r.left, r.top, r.right, r.bottom, r.width(), r.height()); +	if (r.width() > 0 && r.height() > 0) { +		byte *pixels = (byte*)_frontSurface->getBasePtr(r.left, r.top); +		_vm->_system->copyRectToScreen(pixels, _frontSurface->pitch, r.left, r.top, +			r.width(), r.height()); +	} +} + +void GameSys::updateScreen() { + +	debug(1, "GameSys::updateScreen()"); + +	for (uint i = 0; i < _dirtyRects.size(); ++i) +		updateRect(_dirtyRects[i]); + +	if (_dirtyRects.size() > 0) { +		_dirtyRects.clear(); +		_lastUpdateClock = 0; +		_gameSysClock = 0; +	} + +	Common::Rect dstRect, srcRect, rcSrc2; + +	for (int j = 0; j < _gfxItemsCount; ++j) { + +		GfxItem *gfxItem = &_gfxItems[j]; + +		if (!gfxItem->updFlag) +			continue; + +		if (gfxItem->prevFrame.spriteId == -1 || +			!intersectRect(srcRect, _screenRect, gfxItem->prevFrame.rect)) { +			if (gfxItem->currFrame.spriteId != -1 && intersectRect(rcSrc2, _screenRect, gfxItem->currFrame.rect)) +				updateRect(rcSrc2); +		} else if (gfxItem->currFrame.spriteId != -1 && +			intersectRect(rcSrc2, _screenRect, gfxItem->currFrame.rect)) { +			updateRect(srcRect); +			updateRect(rcSrc2); +		} +		gfxItem->prevFrame = gfxItem->currFrame;		 +	} +	 +	updateRect(Common::Rect(0, 0, 800, 600)); + +	debug(1, "GameSys::updateScreen() OK"); + +} + +void GameSys::handleReqRemoveSequenceItem() { +	if (_reqRemoveSequenceItem) { +		int gfxIndex2; +		_reqRemoveSequenceItem = false; +		if (seqFind(_removeSequenceItemSequenceId, _removeSequenceItemValue, &gfxIndex2)) +			_seqItems.remove_at(gfxIndex2); +		if (seqLocateGfx(_removeSequenceItemSequenceId, _removeSequenceItemValue, &gfxIndex2)) { +			int gfxIndex2a = gfxIndex2; +			for (GfxItem *gfxItem = &_gfxItems[gfxIndex2a]; +				gfxIndex2a < _gfxItemsCount && gfxItem->sequenceId == _removeSequenceItemSequenceId && gfxItem->id == _removeSequenceItemValue; +				gfxItem = &_gfxItems[gfxIndex2a]) +				++gfxIndex2a; +			_gfxItemsCount -= gfxIndex2a - gfxIndex2; +			if (_gfxItemsCount != gfxIndex2) +				memcpy(&_gfxItems[gfxIndex2], &_gfxItems[gfxIndex2a], sizeof(GfxItem) * (_gfxItemsCount - gfxIndex2)); +		} +	} +} + +void GameSys::handleReqRemoveSequenceItems() { +	if (_removeSequenceItemsCount > 0) { +		for (int i = 0; i < _removeSequenceItemsCount; ++i) { +			int gfxIndex; +			if (seqFind(_removeSequenceItems[i].sequenceId, _removeSequenceItems[i].id, &gfxIndex)) +				_seqItems.remove_at(gfxIndex); +			seqLocateGfx(_removeSequenceItems[i].sequenceId, _removeSequenceItems[i].id, &gfxIndex); +			for (GfxItem *gfxItem = &_gfxItems[gfxIndex]; +				gfxIndex < _gfxItemsCount && gfxItem->sequenceId == _removeSequenceItems[i].sequenceId && gfxItem->id == _removeSequenceItems[i].id; +				gfxItem = &_gfxItems[gfxIndex]) { +				gfxItem->sequenceId = -1; +				gfxItem->animation = 0; +				gfxItem->soundValue = 0; +				if (_removeSequenceItems[i].a3) { +					gfxItem->currFrame.duration = 0; +					gfxItem->currFrame.spriteId = -1; +					gfxItem->currFrame.soundId = -1; +					gfxItem->currFrame.unkValue = -1; +					gfxItem->updFlag = true; +				} else { +					gfxItem->updFlag = false; +				} +				++gfxIndex; +			} +		} +		_removeSequenceItemsCount = 0; +	} +} + +void GameSys::handleReqRemoveSpriteDrawItems() { +	if (_removeSpriteDrawItemsCount > 0) { +		for (int j = 0; j < _removeSpriteDrawItemsCount; ++j) { +			for (int i = 0; i < _gfxItemsCount; ++i) { +				GfxItem *gfxItem = &_gfxItems[i]; +				if (gfxItem->sequenceId == -1 && !gfxItem->animation && (gfxItem->flags & 1) && +					gfxItem->id == _removeSpriteDrawItems[j].id && _removeSpriteDrawItems[j].surface == gfxItem->surface) { +					gfxItem->flags = 0; +					gfxItem->currFrame.duration = 0; +					gfxItem->currFrame.spriteId = -1; +					gfxItem->currFrame.soundId = -1; +					gfxItem->currFrame.unkValue = -1; +					gfxItem->updFlag = true; +				} +			} +		} +		_removeSpriteDrawItemsCount = 0; +	} +} + +void GameSys::fatUpdateFrame() { + +	debug(1, "GameSys::fatUpdateFrame()"); +	 +	int32 clockDelta = _gameSysClock - _lastUpdateClock; +	_lastUpdateClock = _gameSysClock; +	 +	debug(1, "GameSys::fatUpdateFrame() clockDelta: %d", clockDelta); +	 +	if (clockDelta <= 0) +		return; +	 +	bool updFlag = true; +	int duration, v20, currFrameNum; + +	// NOTE Skipped avi code (reqAviStart) + +	for (int i = 0; i < _gfxItemsCount; ++i) { +		GfxItem *gfxItem = &_gfxItems[i]; +		SequenceAnimation *animation = gfxItem->animation; +		if ((gfxItem->sequenceId != -1 && animation) || (gfxItem->flags & 2) || +			gfxItem->prevFrame.spriteId != -1 || gfxItem->prevFrame.duration > 0) { +			if (gfxItem->sequenceId == -1 || gfxItem->updFlag) { +				if ((gfxItem->flags & 2) && !gfxItem->updFlag) { +					// NOTE Skipped avi code +				} +			} else { +				Sequence *seqItem = seqFind(gfxItem->sequenceId, gfxItem->id, 0); +				if (!animation) { +					updFlag = false; +					gfxItem->sequenceId = -1; +					gfxItem->animation = 0; +					gfxItem->currFrame.duration = 0; +					gfxItem->currFrame.spriteId = -1; +					gfxItem->currFrame.soundId = -1; +					gfxItem->currFrame.unkValue = -1; +					gfxItem->updFlag = true; +				} else if (!seqItem) { +					updFlag = false; +					gfxItem->animation = 0; +					gfxItem->currFrame.duration = 0; +					gfxItem->currFrame.spriteId = -1; +					gfxItem->currFrame.soundId = -1; +					gfxItem->currFrame.unkValue = -1; +					gfxItem->updFlag = true; +				} else if ((seqItem->flags & 4) && clockDelta > 1) { +					updFlag = false; +					if (gfxItem->delayTicks < clockDelta) { +						duration = clockDelta - gfxItem->delayTicks; +						gfxItem->delayTicks = 0; +						if (gfxItem->prevFrame.duration <= duration) +							gfxItem->prevFrame.duration = 1; +						else +							gfxItem->prevFrame.duration -= duration; +					} else { +						gfxItem->delayTicks -= clockDelta; +					} +					gfxItem->updFlag = false; +				} else if (gfxItem->delayTicks < clockDelta) { +					duration = clockDelta - gfxItem->delayTicks; +					gfxItem->delayTicks = 0; +					if (gfxItem->prevFrame.duration <= duration) { +						v20 = 0; +						if (gfxItem->prevFrame.duration > 0) { +							duration -= gfxItem->prevFrame.duration; +							gfxItem->prevFrame.duration = -duration; +						} else { +							gfxItem->prevFrame.duration = 0; +							v20 = 1; +						} +						currFrameNum = gfxItem->currFrameNum; +						if (animation->framesCount > currFrameNum) { +							updFlag = false; +							while (animation->framesCount > currFrameNum && +								animation->frames[currFrameNum].duration <= duration) { +								if (animation->frames[currFrameNum].soundId != -1) +									_soundIds.push_back((gfxItem->sequenceId & 0xFFFF0000) | animation->frames[currFrameNum].soundId); +									duration -= animation->frames[currFrameNum].duration; +									++currFrameNum; +							} +							if (animation->framesCount > currFrameNum) +								gfxItem->currFrame = animation->frames[currFrameNum++]; +							else +								gfxItem->currFrame = animation->frames[currFrameNum - 1]; +							if (gfxItem->currFrame.spriteId != -1 && (seqItem->x != 0 || seqItem->y != 0)) +								gfxItem->currFrame.rect.translate(seqItem->x, seqItem->y); +							// Update sprite scaling										 +							if ((seqItem->flags & 1) && gfxItem->currFrame.rect.bottom >= _backgroundImageValue1 && gfxItem->currFrame.rect.bottom <= _backgroundImageValue3) { +								int v17 = _backgroundImageValue2 + (gfxItem->currFrame.rect.bottom - _backgroundImageValue1) * +									(_backgroundImageValue4 - _backgroundImageValue2) / +									(_backgroundImageValue3 - _backgroundImageValue1); +								gfxItem->currFrame.rect.top = gfxItem->currFrame.rect.bottom - v17 * (gfxItem->currFrame.rect.bottom - gfxItem->currFrame.rect.top) / 1000; +								gfxItem->currFrame.rect.right = v17 * (gfxItem->currFrame.rect.right - gfxItem->currFrame.rect.left) / 1000 + gfxItem->currFrame.rect.left; +								gfxItem->currFrame.isScaled = 1; +							} +							gfxItem->currFrame.duration -= duration; +							if (gfxItem->currFrame.soundId != -1) +								_soundIds.push_back((gfxItem->sequenceId & 0xFFFF0000) | gfxItem->currFrame.soundId); +							gfxItem->currFrameNum = currFrameNum; +							gfxItem->updFlag = true; +						} else if (v20 && gfxItem->prevFrame.spriteId == -1) { +							--_gfxItemsCount; +							if (_gfxItemsCount != i) +								memcpy(&_gfxItems[i], &_gfxItems[i + 1], sizeof(GfxItem) * (_gfxItemsCount - i)); +							--i; +						} else { +							gfxItem->updFlag = false; +						} +					} else { +						updFlag = false; +						gfxItem->prevFrame.duration -= duration; +						gfxItem->updFlag = false; +					} +				} else { +					updFlag = false; +					gfxItem->delayTicks -= clockDelta; +					gfxItem->updFlag = false; +				} +			} +		} else { +			--_gfxItemsCount; +			if (_gfxItemsCount != i) +				memcpy(&_gfxItems[i], &_gfxItems[i + 1], sizeof(GfxItem) * (_gfxItemsCount - i)); +			--i; +		} +	} + +	if (_newSpriteDrawItemsCount > 0) { +		debug(0, "_newSpriteDrawItemsCount: %d", _newSpriteDrawItemsCount); +		for (int k = 0; k < _newSpriteDrawItemsCount; ++k) { +			if (_gfxItemsCount < 50) { +				int insertIndex; +				seqLocateGfx(-1, _newSpriteDrawItems[k].id, &insertIndex); +				if (_gfxItemsCount != insertIndex) +					memcpy(&_gfxItems[insertIndex + 1], &_gfxItems[insertIndex], sizeof(GfxItem) * (_gfxItemsCount - insertIndex)); +				++_gfxItemsCount; +				GfxItem *gfxItem = &_gfxItems[insertIndex]; +				gfxItem->sequenceId = -1; +				gfxItem->id = _newSpriteDrawItems[k].id; +				gfxItem->animation = 0; +				gfxItem->currFrameNum = 0; +				gfxItem->flags = 1; +				gfxItem->delayTicks = 0; +				gfxItem->updFlag = true; +				gfxItem->updRectsCount = 0; +				gfxItem->surface = _newSpriteDrawItems[k].surface; +				gfxItem->prevFrame.duration = 0; +				gfxItem->prevFrame.spriteId = -1; +				gfxItem->prevFrame.soundId = -1; +				gfxItem->prevFrame.unkValue = -1; +				gfxItem->currFrame.duration = 0; +				gfxItem->currFrame.isScaled = 0; +				gfxItem->currFrame.rect = _newSpriteDrawItems[k].rect; +				gfxItem->currFrame.spriteId = _newSpriteDrawItems[k].surface ? 0xCAFEBABE : -1;// TODO +				gfxItem->currFrame.soundId = -1; +				gfxItem->currFrame.unkValue = -1; +			} +		} +		_newSpriteDrawItemsCount = 0; +	} +	 +	if (_grabSpriteChanged) { +		for (int i = 0; i < _gfxItemsCount; ++i) { +			GfxItem *gfxItem = &_gfxItems[i]; +			if (gfxItem->sequenceId == -1 && !gfxItem->animation && (gfxItem->flags & 1) && +				gfxItem->id == _grabSpriteId && gfxItem->surface == _grabSpriteSurface1) { +					gfxItem->currFrame.duration = 0; +					gfxItem->currFrame.isScaled = 0; +					gfxItem->currFrame.rect = _grabSpriteRect; +					gfxItem->currFrame.spriteId = _grabSpriteSurface2 ? 1 : -1;// TODO +					gfxItem->currFrame.soundId = -1; +					gfxItem->currFrame.unkValue = -1; +					gfxItem->updFlag = true; +					gfxItem->surface = _grabSpriteSurface2; +					break; +				} +		} +		_grabSpriteChanged = false; +	} +	 +	// NOTE Skipped avi code (reqAviStart) + +	debug(1, "GameSys::fatUpdateFrame() _fatSequenceItems.size(): %d", _fatSequenceItems.size()); + +	for (uint i = 0; i < _fatSequenceItems.size(); ++i) { +		Sequence *seqItem = &_fatSequenceItems[i]; +		if (((seqItem->flags & 8) || (seqItem->flags & 0x20)) && seqItem->sequenceId2 != -1) { +			duration = 0; +			if (((seqItem->flags & 0x20) && seqLocateGfx(seqItem->sequenceId2, seqItem->id2, 0)) || +				updateSequenceDuration(seqItem->sequenceId2, seqItem->id2, &duration)) { +				int index; +				bool found = false; +				if (seqItem->sequenceId2 == seqItem->sequenceId	&& seqItem->id == seqItem->id2	&& +					seqFind(seqItem->sequenceId, seqItem->id, &index)) { +					_seqItems[index] = *seqItem; +					found = true; +				} else if (_seqItems.size() < 50) { +					index = _seqItems.size(); +					_seqItems.push_back(*seqItem); +					found = true; +				} +				if (found) { +					updFlag = false; +					seqRemoveGfx(seqItem->sequenceId2, seqItem->id2); +					seqRemoveGfx(seqItem->sequenceId, seqItem->id); +					_fatSequenceItems.remove_at(i); +					--i; +					seqInsertGfx(index, duration); +				} +			} +		} else { +			updFlag = false; +			if (seqItem->totalDuration < clockDelta) { +				int index; +				bool found = false; +				duration = clockDelta - seqItem->totalDuration; +				seqItem->totalDuration = 0; +				if (seqFind(seqItem->sequenceId, seqItem->id, &index)) { +					_seqItems[index] = *seqItem; +					found = true; +				} else if (_seqItems.size() < 50) { +					index = _seqItems.size(); +					_seqItems.push_back(*seqItem); +					found = true; +				} +				if (found) { +					seqRemoveGfx(seqItem->sequenceId, seqItem->id); +					_fatSequenceItems.remove_at(i); +					--i; +					seqInsertGfx(index, duration - 1); +				} +			} else { +				seqItem->totalDuration -= clockDelta; +			} +		} +	} + +	debug(1, "GameSys::fatUpdateFrame() _seqItems.size(): %d", _seqItems.size()); + +	for (uint i = 0; i < _seqItems.size(); ++i) { +		Sequence *seqItem = &_seqItems[i]; +		if (seqLocateGfx(seqItem->sequenceId, seqItem->id, 0)) { +			updateAnimationsStatus(seqItem->sequenceId, seqItem->id); +			if (seqItem->flags & 2) { +				int gfxDuration; +				updFlag = false; +				if (updateSequenceDuration(seqItem->sequenceId, seqItem->id, &gfxDuration)) { +					seqRemoveGfx(seqItem->sequenceId, seqItem->id); +					seqInsertGfx(i, gfxDuration); +				} +			} +		} else { +			_seqItems.remove_at(i); +			--i; +		} +	} + +} + +void GameSys::fatUpdate() { + +	debug(1, "GameSys::fatUpdate() _gfxItemsCount: %d", _gfxItemsCount); + +	for (int i = 0; i < _gfxItemsCount; ++i) { +		_gfxItems[i].updFlag = false; +		_gfxItems[i].updRectsCount = 0; +	} +	 +	handleReqRemoveSequenceItem(); +	handleReqRemoveSequenceItems(); +	handleReqRemoveSpriteDrawItems(); +	// NOTE Skipped avi stuff (reqAviStop) +	 +	fatUpdateFrame(); + +} + +void GameSys::updatePlaySounds() { +	for (uint i = 0; i < _soundIds.size(); ++i) +		_vm->playSound(_soundIds[i], false); +	_soundIds.clear(); +} + +bool intersectRect(Common::Rect &intersectingRect, const Common::Rect &r1, const Common::Rect &r2) { +	if (r1.intersects(r2)) { +		intersectingRect = r1.findIntersectingRect(r2); +		return true; +	} else +		return false; +} + +} // End of namespace Gnap diff --git a/engines/gnap/gamesys.h b/engines/gnap/gamesys.h new file mode 100644 index 0000000000..5e996bf844 --- /dev/null +++ b/engines/gnap/gamesys.h @@ -0,0 +1,216 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef GNAP_GAMESYS_H +#define GNAP_GAMESYS_H + +#include "gnap/gnap.h" +#include "gnap/resource.h" +#include "common/array.h" +#include "common/rect.h" +#include "graphics/surface.h" + +namespace Gnap { + +const int kMaxSequenceItems = 40; +const int kMaxSpriteDrawItems = 30; +const int kMaxSoundIds = 50; +const int kMaxSeqItems = 50; +const int kMaxUpdRects = 20; +const int kMaxGfxItems = 50; +const int kMaxAnimations = 12; + +enum { +	kSeqNone		= 0x00, +	kSeqScale		= 0x01, // Enable scaling +	kSeqLoop		= 0x02, // Loop +	kSeqUnk			= 0x04,	// Unknown +	kSeqSyncWait	= 0x08,	// Start if other sequence is done +	kSeqSyncExists	= 0x20	// Start if other sequence exists +}; + +struct Sequence { +	int32 sequenceId; +	int32 id; +	int32 sequenceId2; +	int32 id2; +	uint32 flags; +	int32 totalDuration; +	int16 x, y; +}; + +struct SpriteDrawItem { +	int id; +	Common::Rect rect; +	Graphics::Surface *surface; +}; + +struct RemoveSequenceItem { +	int sequenceId; +	int id; +	int a3; +}; + +struct RemoveSpriteDrawItem { +	int id; +	Graphics::Surface *surface; +}; + +struct GfxItem { +	int sequenceId; +	int id; +	int flags; +	SequenceAnimation *animation; +	int soundValue; +	int field_18; +	int field_1C; +	int currFrameNum; +	int delayTicks; +	bool updFlag; +	int updRectsCount; +	Graphics::Surface *surface; +	Common::Rect updRects[kMaxUpdRects]; +	SequenceFrame prevFrame; +	SequenceFrame currFrame; +	void testUpdRect(const Common::Rect &updRect); +}; + +struct Animation { +	int sequenceId; +	int id; +	int status; +}; + +class GameSys { +public: +	GameSys(GnapEngine *vm); +	~GameSys(); +	void insertSequence(int sequenceId, int a2, int sequenceId2, int a4, int flags, int totalDuration, int16 x, int16 y); +	void insertDirtyRect(const Common::Rect &rect); +	void removeSequence(int sequenceId, int a2, int a3); +	void invalidateGrabCursorSprite(int id, Common::Rect &rect, Graphics::Surface *surface1, Graphics::Surface *surface2); +	void requestClear2(int a1); +	void requestClear1(); +	void requestRemoveSequence(int sequenceId, int a2); +	void waitForUpdate(); +	int isSequenceActive(int sequenceId, int a2); +	void setBackgroundSurface(Graphics::Surface *surface, int a4, int a5, int a6, int a7); +	void setScaleValues(int a1, int a2, int a3, int a4); +	void insertSpriteDrawItem(Graphics::Surface *surface, int x, int y, int id); +	void removeSpriteDrawItem(Graphics::Surface *surface, int a2); +	void drawSpriteToBackground(int x, int y, int resourceId); +	Graphics::Surface *allocSurface(int width, int height); +	Graphics::Surface *createSurface(int resourceId); +	void drawSpriteToSurface(Graphics::Surface *surface, int x, int y, int resourceId); +	void drawTextToSurface(Graphics::Surface *surface, int x, int y, byte r, byte g, byte b, const char *text); +	int getTextWidth(const char *text); +	void fillSurface(Graphics::Surface *surface, int x, int y, int width, int height, byte r, byte g, byte b); +	void setAnimation(int sequenceId, int id, int animationIndex); +	int getAnimationStatus(int animationIndex); +	int getSpriteWidthById(int resourceId); +	int getSpriteHeightById(int resourceId); +	Graphics::Surface *loadBitmap(int resourceId); +	void drawBitmap(int resourceId); +public: +	GnapEngine *_vm; +	 +	Common::Array<Common::Rect> _dirtyRects; + +	SpriteDrawItem _newSpriteDrawItems[kMaxSpriteDrawItems];	 +	int _newSpriteDrawItemsCount; + +	bool _spriteDrawItems1Changed; +	 +	RemoveSequenceItem _removeSequenceItems[kMaxSequenceItems]; +	int _removeSequenceItemsCount; +	 +	RemoveSpriteDrawItem _removeSpriteDrawItems[kMaxSpriteDrawItems]; +	int _removeSpriteDrawItemsCount; +	 +	int _grabSpriteId; +	Common::Rect _grabSpriteRect; +	bool _grabSpriteChanged; +	Graphics::Surface *_grabSpriteSurface1, *_grabSpriteSurface2; +	 +	bool _reqRemoveSequenceItem; +	int _removeSequenceItemSequenceId, _removeSequenceItemValue; + +	Common::Array<int> _soundIds; +	 +	//////////////////////////////////////////////////////////////////////////// +	 +	Common::Array<Sequence> _seqItems; +	Common::Array<Sequence> _fatSequenceItems; +	 +	GfxItem _gfxItems[kMaxGfxItems]; +	int _gfxItemsCount; +	 +	Animation _animations[kMaxAnimations]; +	int _animationsCount; +	 +	int _backgroundImageValue3, _backgroundImageValue1; +	int _backgroundImageValue4, _backgroundImageValue2; +	bool _backgroundImageError; +	 +	int32 _gameSysClock, _lastUpdateClock; + +	Graphics::Surface *_backgroundSurface; +	Graphics::Surface *_frontSurface; +	Common::Rect _screenRect; + +	Sequence *seqFind(int sequenceId, int a2, int *outIndex); +	int seqLocateGfx(int sequenceId, int id, int *outGfxIndex); +	void seqInsertGfx(int index, int duration); +	void seqRemoveGfx(int sequenceId, int id); +	bool updateSequenceDuration(int sequenceId, int id, int *outDuration); +	void updateAnimationsStatus(int sequenceId, int a2); +	 +	void restoreBackgroundRect(const Common::Rect &rect); + +	void blitSurface32(Graphics::Surface *destSurface, int x, int y, Graphics::Surface *sourceSurface, +		Common::Rect &sourceRect, bool transparent); +	void blitSprite32(Graphics::Surface *destSurface, int x, int y, byte *sourcePixels, +		int sourceWidth, Common::Rect &sourceRect, uint32 *sourcePalette, bool transparent); +	void blitSpriteScaled32(Graphics::Surface *destSurface, Common::Rect &frameRect, +		Common::Rect &destRect, byte *sourcePixels, int sourceWidth, Common::Rect &sourceRect, uint32 *sourcePalette); + +	void seqDrawStaticFrame(Graphics::Surface *surface, SequenceFrame &frame, Common::Rect *subRect); +	void seqDrawSpriteFrame(SpriteResource *spriteResource, SequenceFrame &frame, Common::Rect *subRect); + +	void drawSprites(); +	void updateRect(const Common::Rect &r); +	void updateScreen(); +	 +	void handleReqRemoveSequenceItem(); +	void handleReqRemoveSequenceItems(); +	void handleReqRemoveSpriteDrawItems(); +	void fatUpdateFrame(); +	void fatUpdate(); +	void updatePlaySounds(); + +}; + +bool intersectRect(Common::Rect &intersectingRect, const Common::Rect &r1, const Common::Rect &r2); + +} // End of namespace Gnap + +#endif // GNAP_GAMESYS_H diff --git a/engines/gnap/gnap.cpp b/engines/gnap/gnap.cpp new file mode 100644 index 0000000000..08f598551e --- /dev/null +++ b/engines/gnap/gnap.cpp @@ -0,0 +1,2404 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/datarchive.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" +#include "gnap/sound.h" + +#include "common/config-manager.h" +#include "common/debug-channels.h" +#include "common/error.h" +#include "common/fs.h" +#include "common/timer.h" + +#include "engines/util.h" + +#include "graphics/cursorman.h" + +namespace Gnap { + +static const int kCursors[] = { +	LOOK_CURSOR, +	GRAB_CURSOR, +	TALK_CURSOR, +	PLAT_CURSOR +}; + +static const int kDisabledCursors[] = { +	NOLOOK_CURSOR, +	NOGRAB_CURSOR, +	NOTALK_CURSOR, +	NOPLAT_CURSOR +}; + +static const char *kCursorNames[] = { +	"LOOK_CURSOR", +	"GRAB_CURSOR", +	"TALK_CURSOR", +	"PLAT_CURSOR", +	"NOLOOK_CURSOR", +	"NOGRAB_CURSOR", +	"NOTALK_CURSOR", +	"NOPLAT_CURSOR", +	"EXIT_L_CURSOR", +	"EXIT_R_CURSOR", +	"EXIT_U_CURSOR", +	"EXIT_D_CURSOR", +	"EXIT_NE_CURSOR", +	"EXIT_NW_CURSOR", +	"EXIT_SE_CURSOR", +	"EXIT_SW_CURSOR", +	"WAIT_CURSOR" +}; + + +static const int kCursorSpriteIds[30] = { +	0x005, 0x008, 0x00A, 0x004, 0x009, 0x003, +	0x006, 0x007, 0x00D, 0x00F, 0x00B, 0x00C, +	0x019, 0x01C, 0x015, 0x014, 0x010, 0x01A, +	0x018, 0x013, 0x011, 0x012, 0x01B, 0x016, +	0x017, 0x01D, 0x01E, 0x01F, 0x76A, 0x76B +}; + +static const char *kSceneNames[] = { +	"open", "pigpn", "truck", "creek", "mafrm", "frbrn", "inbrn", "crash", +	"porch", "barbk", "kitch", "bar", "juke", "wash", "john", "jkbox", +	"brawl", "stret", "frtoy", "intoy", "frgro", "park", "cash", "ingro", +	"frcir", "booth", "circ", "outcl", "incln", "monk", "elcir", "beer", +	"pig2", "trk2", "creek", "frbrn", "inbrn", "mafrm", "infrm", "efair", +	"fair", "souv", "chick", "ship", "kiss", "disco", "boot", "can", +	"can2", "drive", "tung", "puss", "space", "phone", "can3" +}; + +GnapEngine::GnapEngine(OSystem *syst, const ADGameDescription *gd) : +	Engine(syst), _gameDescription(gd) { +	 +	_random = new Common::RandomSource("gnap"); +	 +	Engine::syncSoundSettings(); + +} + +GnapEngine::~GnapEngine() { + +	delete _random; + +} + +Common::Error GnapEngine::run() { +	// Initialize the graphics mode to ARGB8888 +	Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); +	initGraphics(800, 600, true, &format); + +	// We do not support color conversion yet +	if (_system->getScreenFormat() != format) +		return Common::kUnsupportedColorMode; +		 +	_lastUpdateClock = 0; +		 +	// >>>>> Variable initialization +	_cursorIndex = -1; +	_verbCursor = 1; +	invClear(); +	clearFlags(); +	_grabCursorSprite = 0; +	_newGrabCursorSpriteIndex = -1; +	_backgroundSurface = 0; +	_isStockDatLoaded = false; +	_gameDone = false; +	_isPaused = false; +	_pauseSprite = 0; + +	//////////////////////////////////////////////////////////////////////////// + +	_exe = new Common::PEResources(); +	if (!_exe->loadFromEXE("ufos.exe")) +		error("Could not load ufos.exe"); + +	_dat = new DatManager(); +	_spriteCache = new SpriteCache(_dat); +	_soundCache = new SoundCache(_dat); +	_sequenceCache = new SequenceCache(_dat); +	_gameSys = new GameSys(this); +	_soundMan = new SoundMan(this); +	 +	_menuBackgroundSurface = 0; +	 +	initGlobalSceneVars(); + +#if 1 + +	mainLoop(); + +#else +	 +	Graphics::Surface *testBack = new Graphics::Surface(); +	testBack->create(800, 600, _system->getScreenFormat()); +	//testBack->fillRect(Common::Rect(0, 0, 800, 600), 0xFFFFFFFF); +	testBack->fillRect(Common::Rect(0, 0, 800, 600), 0xFF000000); +	 +	_currentSceneNum = 26; + +    Common::String datFilename = Common::String::format("%s_n.dat", kSceneNames[_currentSceneNum]); +	_dat->open(0, datFilename.c_str()); +	 +	_gameSys->setBackgroundSurface(testBack, 0, 500, 1, 1000); + +	_gameSys->insertSequence(0x5b, 100, -1, -1, 0, 0, 0, 0); + +	CursorMan.showMouse(true); +	 +	while (!shouldQuit()) { +		Common::Event event; + +		while (_eventMan->pollEvent(event)) { +			switch (event.type) { +			case Common::EVENT_KEYDOWN: +				break; +			case Common::EVENT_LBUTTONUP: +			case Common::EVENT_LBUTTONDOWN: +			case Common::EVENT_RBUTTONUP: +			case Common::EVENT_RBUTTONDOWN: +			case Common::EVENT_MOUSEMOVE: +				break; +			case Common::EVENT_QUIT: +				quitGame(); +				break; +			default: +				break; +			} +		} +		 +		_gameSys->fatUpdate(); +		_gameSys->drawSprites(); +		_gameSys->updateScreen(); +		_gameSys->_gameSysClock++; +		updateTimers(); + +		_system->updateScreen(); +		_system->delayMillis(100); + +	} + +	_dat->close(0); +	 +	testBack->free(); +	delete testBack; + +	return Common::kNoError; + +#endif + +	delete _soundMan; +	delete _gameSys; +	delete _sequenceCache; +	delete _soundCache; +	delete _spriteCache; +	delete _dat; +	 +	delete _exe; + +	debug("run() done"); +	 +	return Common::kNoError; +} + +bool GnapEngine::hasFeature(EngineFeature f) const { +	return +		false; +} + +void GnapEngine::updateEvents() { +	Common::Event event; + +	while (_eventMan->pollEvent(event)) { +		switch (event.type) { +		case Common::EVENT_KEYDOWN: +			_keyPressState[event.kbd.keycode] = 1; +			_keyDownState[event.kbd.keycode] = 1; +			break; +		case Common::EVENT_KEYUP: +			_keyDownState[event.kbd.keycode] = 0; +  			break; +		case Common::EVENT_MOUSEMOVE: +  			_mouseX = event.mouse.x; +  			_mouseY = event.mouse.y; +  			break; +		case Common::EVENT_LBUTTONUP: +  			_mouseButtonState.left = false; +  			break; +		case Common::EVENT_LBUTTONDOWN: +			_leftClickMouseX = event.mouse.x; +			_leftClickMouseY = event.mouse.y; +			_mouseButtonState.left = true; +			_mouseClickState.left = true; +  			break; +		case Common::EVENT_RBUTTONUP: +			_mouseButtonState.right = false; +  			break; +		case Common::EVENT_RBUTTONDOWN: +  			_mouseButtonState.right = true; +  			_mouseClickState.right = true; +  			break; +		case Common::EVENT_QUIT: +			quitGame(); +			break; +		default: +			break; +		} +	} +} + +void GnapEngine::gameUpdateTick() { +	updateEvents(); + +	// TODO Check _gameDone in the various game loops +	if (shouldQuit()) { +		_gameDone = true; +		_sceneDone = true; +	} + +	// TODO Improve this (variable frame delay to keep ~15fps) +	int currClock = _system->getMillis(); +	if (currClock >= _lastUpdateClock + 66) { +		_gameSys->fatUpdate(); +		_gameSys->drawSprites(); +		_gameSys->updateScreen(); +		_gameSys->updatePlaySounds(); +		_gameSys->_gameSysClock++; +		updateTimers(); +		_lastUpdateClock = currClock; +	} + +	_soundMan->update(); +	_system->updateScreen(); +	_system->delayMillis(5); + +} + +void GnapEngine::saveTimers() { +	for (int i = 0; i < kMaxTimers; ++i ) +		_savedTimers[i] = _timers[i]; +} + +void GnapEngine::restoreTimers() { +	for (int i = 0; i < kMaxTimers; ++i ) +		_timers[i] = _savedTimers[i]; +} + +void GnapEngine::pauseGame() { +	if (!_isPaused) { +		saveTimers(); +		hideCursor(); +		setGrabCursorSprite(-1); +		_pauseSprite = _gameSys->createSurface(0x1076C); +		_gameSys->insertSpriteDrawItem(_pauseSprite, (800 - _pauseSprite->w) / 2, (600 - _pauseSprite->h) / 2, 356); +		_lastUpdateClock = 0; +		gameUpdateTick(); +		// TODO playMidi("pause.mid"); +		_isPaused = true; +	} +} + +void GnapEngine::resumeGame() { +	if (_isPaused) { +		restoreTimers(); +		_gameSys->removeSpriteDrawItem(_pauseSprite, 356); +		_lastUpdateClock = 0; +		gameUpdateTick(); +		deleteSurface(&_pauseSprite); +		// TODO stopMidi(); +		_isPaused = false; +		clearAllKeyStatus1(); +		_mouseClickState.left = false; +		_mouseClickState.right = false; +		showCursor(); +		_gameSys->_gameSysClock = 0; +		_gameSys->_lastUpdateClock = 0; +	} +} + +void GnapEngine::updatePause() { +	while (_isPaused) { +		gameUpdateTick(); +		if (isKeyStatus1(Common::KEYCODE_p)) { +			clearKeyStatus1(Common::KEYCODE_p); +			resumeGame(); +		} +		//_system->delayMillis(100); +	} +} + +int GnapEngine::getRandom(int max) { +	return _random->getRandomNumber(max - 1); +} + +int GnapEngine::readSavegameDescription(int savegameNum, Common::String &description) { +	description = Common::String::format("Savegame %d", savegameNum); +	return 0; +} + +int GnapEngine::loadSavegame(int savegameNum) { +	return 1; +} + +void GnapEngine::delayTicks(int a1) { +	// TODO +	gameUpdateTick(); +} + +void GnapEngine::delayTicksCursor(int a1) { +	// TODO +	gameUpdateTick(); +} + +void GnapEngine::setHotspot(int index, int16 x1, int16 y1, int16 x2, int16 y2, uint16 flags, +	int16 walkX, int16 walkY) { +	_hotspots[index].x1 = x1; +	_hotspots[index].y1 = y1; +	_hotspots[index].x2 = x2; +	_hotspots[index].y2 = y2; +	_hotspots[index].flags = flags; +	_hotspots[index].id = index; +	_hotspotsWalkPos[index].x = walkX; +	_hotspotsWalkPos[index].y = walkY; +} + +int GnapEngine::getHotspotIndexAtPos(int16 x, int16 y) { +	for (int i = 0; i < _hotspotsCount; ++i) +		if (!_hotspots[i].isFlag(SF_DISABLED) && _hotspots[i].isPointInside(x, y)) +			return i; +	return -1; +} + +void GnapEngine::updateCursorByHotspot() { +	if (!_isWaiting) { +		int hotspotIndex = getHotspotIndexAtPos(_mouseX, _mouseY); + +#if 1 +		// NOTE This causes some display glitches so don't worry +		char t[256]; +		sprintf(t, "hotspot = %d", hotspotIndex); +		_gameSys->fillSurface(0, 10, 10, 80, 16, 0, 0, 0); +		_gameSys->drawTextToSurface(0, 10, 10, 255, 255, 255, t); +#endif		 + +		if (hotspotIndex < 0) +			setCursor(kDisabledCursors[_verbCursor]); +		else if (_hotspots[hotspotIndex].flags & SF_EXIT_L_CURSOR) +			setCursor(EXIT_L_CURSOR); +		else if (_hotspots[hotspotIndex].flags & SF_EXIT_R_CURSOR) +			setCursor(EXIT_R_CURSOR); +		else if (_hotspots[hotspotIndex].flags & SF_EXIT_U_CURSOR) +			setCursor(EXIT_U_CURSOR); +		else if (_hotspots[hotspotIndex].flags & SF_EXIT_D_CURSOR) +			setCursor(EXIT_D_CURSOR); +		else if (_hotspots[hotspotIndex].flags & SF_EXIT_NE_CURSOR) +			setCursor(EXIT_NE_CURSOR); +		else if (_hotspots[hotspotIndex].flags & SF_EXIT_NW_CURSOR) +			setCursor(EXIT_NW_CURSOR); +		else if (_hotspots[hotspotIndex].flags & SF_EXIT_SE_CURSOR) +			setCursor(EXIT_SE_CURSOR); +		else if (_hotspots[hotspotIndex].flags & SF_EXIT_SW_CURSOR) +			setCursor(EXIT_SW_CURSOR); +		else if (_hotspots[hotspotIndex].flags & (1 << _verbCursor)) +			setCursor(kCursors[_verbCursor]); +		else +			setCursor(kDisabledCursors[_verbCursor]); +	} +	// Update platypus hotspot +	_hotspots[0].x1 = _gridMinX + 75 * _platX - 30; +	_hotspots[0].y1 = _gridMinY + 48 * _platY - 100; +	_hotspots[0].x2 = _gridMinX + 75 * _platX + 30; +	_hotspots[0].y2 = _gridMinY + 48 * _platY; +} + +int GnapEngine::getClickedHotspotId() { +	int result = -1; +	if (_isWaiting) +		_mouseClickState.left = false; +	else if (_mouseClickState.left) { +		int hotspotIndex = getHotspotIndexAtPos(_leftClickMouseX, _leftClickMouseY); +		if (hotspotIndex >= 0) { +			_mouseClickState.left = false; +			_timers[3] = 300; +			result = _hotspots[hotspotIndex].id; +		} +	} +	return result; +} + +int GnapEngine::getInventoryItemSpriteNum(int index) { +	return kCursorSpriteIds[index]; +} + +void GnapEngine::updateMouseCursor() { +	if (_mouseClickState.right) { +		// Switch through the verb cursors +		_mouseClickState.right = false; +		_timers[3] = 300; +		_verbCursor = (_verbCursor + 1) % 4; +		if (!isFlag(0) && _verbCursor == PLAT_CURSOR && _cursorValue == 1) +			_verbCursor = (_verbCursor + 1) % 4; +		if (!_isWaiting) +			setCursor(kDisabledCursors[_verbCursor]); +		setGrabCursorSprite(-1); +	} +	if (_isWaiting && ((_gnapActionStatus < 0 && _beaverActionStatus < 0) || _sceneWaiting)) { +		setCursor(kDisabledCursors[_verbCursor]); +		_isWaiting = false; +	} else if (!_isWaiting && (_gnapActionStatus >= 0 || _beaverActionStatus >= 0) && !_sceneWaiting) { +		setCursor(WAIT_CURSOR); +		_isWaiting = true; +	} +} + +void GnapEngine::setVerbCursor(int verbCursor) { +	_verbCursor = verbCursor; +	if (!_isWaiting) +		setCursor(kDisabledCursors[_verbCursor]); +} + +void GnapEngine::setCursor(int cursorIndex) { +	if (_cursorIndex != cursorIndex) { +		const char *cursorName = kCursorNames[cursorIndex]; +		Graphics::WinCursorGroup *cursorGroup = Graphics::WinCursorGroup::createCursorGroup(*_exe, Common::WinResourceID(cursorName)); +		if (cursorGroup) { +			Graphics::Cursor *cursor = cursorGroup->cursors[0].cursor; +			CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), +				cursor->getHotspotX(), cursor->getHotspotY(), cursor->getKeyColor()); +			CursorMan.replaceCursorPalette(cursor->getPalette(), 0, 256); +			delete cursorGroup; +		} +		_cursorIndex = cursorIndex; +	} +} + +void GnapEngine::showCursor() { +	CursorMan.showMouse(true); +} + +void GnapEngine::hideCursor() { +	CursorMan.showMouse(false); +} + +void GnapEngine::setGrabCursorSprite(int index) { +	freeGrabCursorSprite(); +	if (index >= 0) { +		createGrabCursorSprite(makeRid(1, kCursorSpriteIds[index])); +		setVerbCursor(GRAB_CURSOR); +	} +	_grabCursorSpriteIndex = index; +} + +void GnapEngine::createGrabCursorSprite(int spriteId) { +	_grabCursorSprite = _gameSys->createSurface(spriteId); +	_gameSys->insertSpriteDrawItem(_grabCursorSprite, +		_mouseX - (_grabCursorSprite->w / 2), +		_mouseY - (_grabCursorSprite->h / 2), +		300); +	delayTicks(5); +} + +void GnapEngine::freeGrabCursorSprite() { +	if (_grabCursorSprite) { +		_gameSys->removeSpriteDrawItem(_grabCursorSprite, 300); +		_gameSys->removeSpriteDrawItem(_grabCursorSprite, 301); +		delayTicks(5); +		deleteSurface(&_grabCursorSprite); +	} +} + +void GnapEngine::updateGrabCursorSprite(int x, int y) { +	if (_grabCursorSprite) { +		int newGrabCursorX = _mouseX - (_grabCursorSprite->w / 2) - x; +		int newGrabCursorY = _mouseY - (_grabCursorSprite->h / 2) - y; +		if (_currGrabCursorX != newGrabCursorX || _currGrabCursorY != newGrabCursorY) { +			_currGrabCursorX = newGrabCursorX; +			_currGrabCursorY = newGrabCursorY; +			Common::Rect rect(newGrabCursorX, newGrabCursorY, +				newGrabCursorX + _grabCursorSprite->w, newGrabCursorY + _grabCursorSprite->h); +			_gameSys->invalidateGrabCursorSprite(300, rect, _grabCursorSprite, _grabCursorSprite); +		} +	} +} + +void GnapEngine::invClear() { +	_inventory = 0; +} + +void GnapEngine::invAdd(int itemId) { +	_inventory |= (1 << itemId); +} + +void GnapEngine::invRemove(int itemId) { +	_inventory &= ~(1 << itemId); +} + +bool GnapEngine::invHas(int itemId) { +	return (_inventory & (1 << itemId)) != 0; +} + +void GnapEngine::clearFlags() { +	_gameFlags = 0; +} + +void GnapEngine::setFlag(int num) { +	_gameFlags |= (1 << num); +} + +void GnapEngine::clearFlag(int num) { +	_gameFlags &= ~(1 << num); +} + +bool GnapEngine::isFlag(int num) { +	return (_gameFlags & (1 << num)) != 0; +} + +Graphics::Surface *GnapEngine::addFullScreenSprite(int resourceId, int id) { +	_fullScreenSpriteId = id; +	_fullScreenSprite = _gameSys->createSurface(resourceId); +	_gameSys->insertSpriteDrawItem(_fullScreenSprite, 0, 0, id); +	return _fullScreenSprite; +} + +void GnapEngine::removeFullScreenSprite() { +	_gameSys->removeSpriteDrawItem(_fullScreenSprite, _fullScreenSpriteId); +	deleteSurface(&_fullScreenSprite); +} + +void GnapEngine::showFullScreenSprite(int resourceId) { +	hideCursor(); +	setGrabCursorSprite(-1); +	addFullScreenSprite(resourceId, 256); +	while (!_mouseClickState.left && !isKeyStatus1(Common::KEYCODE_ESCAPE) && +		!isKeyStatus1(Common::KEYCODE_SPACE) && !isKeyStatus1(29)) { +		gameUpdateTick(); +	} +	_mouseClickState.left = false; +	clearKeyStatus1(Common::KEYCODE_ESCAPE); +	clearKeyStatus1(29); +	clearKeyStatus1(Common::KEYCODE_SPACE); +	removeFullScreenSprite(); +	showCursor(); +} + +void GnapEngine::queueInsertDeviceIcon() { +	_gameSys->insertSequence(0x10849, 20, 0, 0, kSeqNone, 0, _deviceX1, _deviceY1); +} + +void GnapEngine::insertDeviceIconActive() { +	_gameSys->insertSequence(0x1084A, 21, 0, 0, kSeqNone, 0, _deviceX1, _deviceY1); +} + +void GnapEngine::removeDeviceIconActive() { +	_gameSys->removeSequence(0x1084A, 21, 1); +} + +void GnapEngine::setDeviceHotspot(int hotspotIndex, int x1, int y1, int x2, int y2) { +	_deviceX1 = x1; +	_deviceX2 = x2; +	_deviceY1 = y1; +	_deviceY2 = y2; +	if (x1 == -1) +		_deviceX1 = 730; +	if (x2 == -1) +		_deviceX2 = 780; +	if (y1 == -1) +		_deviceY1 = 14; +	if (y2 == -1) +		_deviceY2 = 79; +	_hotspots[hotspotIndex].x1 = _deviceX1; +	_hotspots[hotspotIndex].y1 = _deviceY1; +	_hotspots[hotspotIndex].x2 = _deviceX2; +	_hotspots[hotspotIndex].y2 = _deviceY2; +	_hotspots[hotspotIndex].flags = SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR; +	_hotspots[hotspotIndex].id = hotspotIndex; +} + +int GnapEngine::getSequenceTotalDuration(int resourceId) { +	SequenceResource *sequenceResource = _sequenceCache->get(resourceId);	 +	int maxValue = 0; +	for (int i = 0; i < sequenceResource->_animationsCount; ++i) { +		SequenceAnimation *animation = &sequenceResource->_animations[i]; +		if (animation->field_4 + animation->field_A > maxValue) +			maxValue = animation->field_4 + animation->field_A; +	} +	int totalDuration = maxValue + sequenceResource->_totalDuration; +	_sequenceCache->release(resourceId); +	return totalDuration; +} + +bool GnapEngine::isSoundPlaying(int resourceId) { +	return _soundMan->isSoundPlaying(resourceId); +} + +void GnapEngine::playSound(int resourceId, bool looping) { +	debug(0, "playSound(%08X, %d)", resourceId, looping); +	_soundMan->playSound(resourceId, looping); +} + +void GnapEngine::stopSound(int resourceId) { +	_soundMan->stopSound(resourceId); +} + +void GnapEngine::setSoundVolume(int resourceId, int volume) { +	_soundMan->setSoundVolume(resourceId, volume); +} + +void GnapEngine::updateTimers() { +	for (int i = 0; i < kMaxTimers; ++i) +		if (_timers[i] > 0) +			--_timers[i]; +} + +void GnapEngine::initGameFlags(int num) { +	invClear(); +	invAdd(kItemMagazine); +	switch (num) { +	case 1: +		setFlag(26); +		break; +	case 2: +		clearFlags(); +		break; +	case 3: +		invAdd(kItemDiceQuarterHole); +		clearFlags(); +		break; +	case 4: +		invAdd(kItemDiceQuarterHole); +		invAdd(kItemHorn); +		invAdd(kItemLightbulb); +		clearFlags(); +		setFlag(0); +		setFlag(1); +		setFlag(2); +		setFlag(3); +		setFlag(4); +		setFlag(5); +		setFlag(6); +		setFlag(7); +		break; +	} + +	//DEBUG! +//	setFlag(0); // Enable platypus +	setFlag(25); +	invClear(); +	invAdd(kItemMagazine); +#if 0 +	invAdd(kItemDisguise); +#endif +#if 1 +	//invAdd(kItemGas); +	invAdd(kItemJoint); +	//invAdd(kItemKeys); +	invAdd(kItemWrench); +	//invAdd(kItemTongs); +	invAdd(kItemDiceQuarterHole); +	//invAdd(kItemPill); +	invAdd(kItemBucketWithBeer); +	invAdd(kItemChickenBucket); +	invAdd(kItemGum); +	invAdd(kItemPicture); +#endif +} + +void GnapEngine::loadStockDat() { +	if (!_isStockDatLoaded) { +		_isStockDatLoaded = true; +		_dat->open(1, "stock_n.dat"); +		//createMenuSprite(); +		// NOTE Skipped preloading of data +	} +} + +void GnapEngine::mainLoop() { +	 +	_newCursorValue = 1; +	_cursorValue = -1; +	_newSceneNum = 0; +	_currentSceneNum = 55; +	_prevSceneNum = 55; +	invClear(); +	clearFlags(); +	_grabCursorSpriteIndex = -1; +	_grabCursorSprite = 0; + +	debug("MainLoop #1"); + +	// > DEBUG BEGIN +	_currentSceneNum = 53; +	_newSceneNum = 27; +	_newCursorValue = 3; +	// < DEBUG END + +	loadStockDat(); + +	while (!_gameDone) { +	 +		debug("New scene: %d", _newSceneNum); +	 +		_prevSceneNum = _currentSceneNum; +		_currentSceneNum = _newSceneNum; +		 +		debug("GnapEngine::mainLoop() _prevSceneNum: %d; _currentSceneNum: %d", _prevSceneNum, _currentSceneNum); + +		if (_newCursorValue != _cursorValue) { +			debug("_newCursorValue: %d", _newCursorValue); +			_cursorValue = _newCursorValue; +			if (!_wasSavegameLoaded) +				initGameFlags(_cursorValue); +		} + +		_sceneSavegameLoaded = _wasSavegameLoaded; +		_wasSavegameLoaded = false; + +		initScene(); +		 +		runSceneLogic(); +		afterScene(); +		 +		_soundMan->stopAll(); + +		// Force purge all resources +		_sequenceCache->purge(true); +		_soundCache->purge(true); +		_spriteCache->purge(true); + +		if (isKeyStatus1(28)) { +			clearKeyStatus1(28); +			if (_debugLevel == 4) +				_gameDone = true; +		} + +	} + +	if (_backgroundSurface) +		deleteSurface(&_backgroundSurface); +	 +	_dat->close(1); +	// TODO freeMenuSprite(); +	// TODO freeFont(); + +	debug("MainLoop #XXX2"); + +} + +void GnapEngine::initScene() { + +	Common::String datFilename; +	 +	_isLeavingScene = false; +	_sceneDone = false; +	_newSceneNum = 55; +	_gnapActionStatus = -1; +	_beaverActionStatus = -1; +	gnapInitBrainPulseRndValue(); +	hideCursor(); +	clearAllKeyStatus1(); +	_mouseClickState.left = false; +	_mouseClickState.right = false; +	_sceneClickedHotspot = -1; + +	datFilename = Common::String::format("%s_n.dat", kSceneNames[_currentSceneNum]); + +	debug("GnapEngine::initScene() datFilename: %s", datFilename.c_str()); + +	_dat->open(0, datFilename.c_str()); + +	int backgroundId = initSceneLogic(); + +	if (!_backgroundSurface) { +		if (_currentSceneNum != 0) +			_backgroundSurface = _gameSys->loadBitmap(makeRid(1, 0x8AA)); +		else +			_backgroundSurface = _gameSys->loadBitmap(makeRid(0, backgroundId)); +		_gameSys->setBackgroundSurface(_backgroundSurface, 0, 500, 1, 1000); +	} + +	if (_currentSceneNum != 0 && _currentSceneNum != 16 && _currentSceneNum != 47 && +		_currentSceneNum != 48 && _currentSceneNum != 54) { +		_gameSys->drawBitmap(backgroundId); +	} + +	if ((_cursorValue == 4 && isFlag(12)) || _currentSceneNum == 41) +		playSound(makeRid(1, 0x8F6), true); + +} + +void GnapEngine::endSceneInit() { +	showCursor(); +	if (_newGrabCursorSpriteIndex >= 0) +		setGrabCursorSprite(_newGrabCursorSpriteIndex); +} + +void GnapEngine::afterScene() { + +	if (_gameDone) +		return; +	 +	if (_newCursorValue == _cursorValue && _newSceneNum != 0 && _newSceneNum != 16 && +		_newSceneNum != 47 && _newSceneNum != 48 && _newSceneNum != 54 && _newSceneNum != 49 && +		_newSceneNum != 50 && _newSceneNum != 51 && _newSceneNum != 52) +		_newGrabCursorSpriteIndex = _grabCursorSpriteIndex; +	else +		_newGrabCursorSpriteIndex = -1; + +	setGrabCursorSprite(-1); + +	_gameSys->requestClear2(0); +	_gameSys->requestClear1(); +	_gameSys->waitForUpdate(); + +	_gameSys->requestClear2(0); +	_gameSys->requestClear1(); +	_gameSys->waitForUpdate(); + +	screenEffect(0, 0, 0, 0); + +	_dat->close(0); + +	for (int animationIndex = 0; animationIndex < 12; ++animationIndex) +		_gameSys->setAnimation(0, 0, animationIndex); + +	clearKeyStatus1(Common::KEYCODE_p); + +	_mouseClickState.left = false; +	_mouseClickState.right = false; + +} + +void GnapEngine::checkGameKeys() { +	if (isKeyStatus1(Common::KEYCODE_p)) { +		clearKeyStatus1(Common::KEYCODE_p); +		pauseGame(); +		updatePause(); +	} +	// TODO? Debug input +} + +void GnapEngine::startSoundTimerA(int timerIndex) { +	_soundTimerIndexA = timerIndex; +	_timers[timerIndex] = getRandom(50) + 100; +} + +int GnapEngine::playSoundA() { + +	static const int kSoundIdsA[] = { +		0x93E, 0x93F, 0x941, 0x942, 0x943, 0x944, +		0x945, 0x946, 0x947, 0x948, 0x949 +	}; + +	int soundId = -1; +	 +	if (!_timers[_soundTimerIndexA]) { +		_timers[_soundTimerIndexA] = getRandom(50) + 100; +		soundId = kSoundIdsA[getRandom(11)]; +		playSound(soundId | 0x10000, 0); +	} +	return soundId; +} + +void GnapEngine::startSoundTimerB(int timerIndex) { +	_soundTimerIndexB = timerIndex; +	_timers[timerIndex] = getRandom(50) + 150; +} + +int GnapEngine::playSoundB() { + +	static const int kSoundIdsB[] = { +		0x93D, 0x929, 0x92A, 0x92B, 0x92C, 0x92D, +		0x92E, 0x92F, 0x930, 0x931, 0x932, 0x933, +		0x934, 0x935, 0x936, 0x937, 0x938, 0x939, +		0x93A +	}; + +	int soundId = -1; +	 +	if (!_timers[_soundTimerIndexB]) { +		_timers[_soundTimerIndexB] = getRandom(50) + 150; +		soundId = kSoundIdsB[getRandom(19)]; +		playSound(soundId | 0x10000, 0); +	} +	return soundId; +} + +void GnapEngine::startSoundTimerC(int timerIndex) { +	_soundTimerIndexC = timerIndex; +	_timers[timerIndex] = getRandom(50) + 150; +} + +int GnapEngine::playSoundC() { + +	static const int kSoundIdsC[] = { +		0x918, 0x91F, 0x920, 0x922, 0x923, 0x924, +		0x926 +	}; + +	int soundId = -1; + +	if (!_timers[_soundTimerIndexC]) { +		_timers[_soundTimerIndexC] = getRandom(50) + 150; +		soundId = kSoundIdsC[getRandom(7)] ; +		playSound(soundId | 0x10000, 0); +	} +	return soundId; +} + +void GnapEngine::startIdleTimer(int timerIndex) { +	_idleTimerIndex = timerIndex; +	_timers[timerIndex] = 3000; +} + +void GnapEngine::updateIdleTimer() { +	if (!_timers[_idleTimerIndex]) { +		_timers[_idleTimerIndex] = 3000; +		_gameSys->insertSequence(0x1088B, 255, 0, 0, kSeqNone, 0, 0, 75); +	} +} + +void GnapEngine::screenEffect(int dir, byte r, byte g, byte b) { +	if (dir == 1) { +		for (int y = 300; y < 600; y += 50) { +			_gameSys->fillSurface(0, 0, y, 800, 50, r, g, b); +			_gameSys->fillSurface(0, 0, 549 - y + 1, 800, 50, r, g, b); +			gameUpdateTick(); +			_system->delayMillis(50); +		} +	} else { +		for (int y = 0; y < 300; y += 50) { +			_gameSys->fillSurface(0, 0, y, 800, 50, r, g, b); +			_gameSys->fillSurface(0, 0, 549 - y + 1, 800, 50, r, g, b); +			gameUpdateTick(); +			_system->delayMillis(50); +		} +	} +} + +bool GnapEngine::isKeyStatus1(int key) { +	return _keyPressState[key] != 0;; +} + +bool GnapEngine::isKeyStatus2(int key) { +	return _keyDownState[key] != 0;; +} + +void GnapEngine::clearKeyStatus1(int key) { +	_keyPressState[key] = 0; +	_keyDownState[key] = 0; +} + +void GnapEngine::clearAllKeyStatus1() { +	_keyStatus1[0] = 0; +	_keyStatus1[1] = 0; +	memset(_keyPressState, 0, sizeof(_keyPressState)); +	memset(_keyDownState, 0, sizeof(_keyDownState)); +} + +void GnapEngine::deleteSurface(Graphics::Surface **surface) { +	if (surface && *surface) { +		(*surface)->free(); +		delete *surface; +		*surface = 0; +	} +} + +int GnapEngine::getGnapSequenceId(int kind, int gridX, int gridY) { +	int sequenceId = 0; +	 +	switch (kind) { + +	case gskPullOutDevice: +		if (gridX > 0 && gridY > 0) { +			if (_gnapY > gridY) { +				if (_gnapX > gridX) { +					sequenceId = 0x83F; +					_gnapIdleFacing = 5; +				} else { +					sequenceId = 0x83D; +					_gnapIdleFacing = 7; +				} +			} else { +				if (_gnapX > gridX) { +					sequenceId = 0x83B; +					_gnapIdleFacing = 3; +				} else { +					sequenceId = 0x839; +					_gnapIdleFacing = 1; +				} +			} +		} else { +			switch (_gnapIdleFacing) { +			case 1: +				sequenceId = 0x839; +				break; +			case 3: +				sequenceId = 0x83B; +				break; +			case 7: +				sequenceId = 0x83D; +				break; +			default: +				sequenceId = 0x83F; +				break; +			} +		} +		break; + +	case gskPullOutDeviceNonWorking: +		if (gridX > 0 && gridY > 0) { +			if (_gnapY > gridY) { +				if (_gnapX > gridX) { +					sequenceId = 0x829; +					_gnapIdleFacing = 5; +				} else { +					sequenceId = 0x828; +					_gnapIdleFacing = 7; +				} +			} else { +				if (_gnapX > gridX) { +					sequenceId = 0x827; +					_gnapIdleFacing = 3; +				} else { +					sequenceId = 0x826; +					_gnapIdleFacing = 1; +				} +			} +		} else { +			switch (_gnapIdleFacing) { +			case 1: +				sequenceId = 0x826; +				break; +			case 3: +				sequenceId = 0x827; +				break; +			case 7: +				sequenceId = 0x828; +				break; +			default: +				sequenceId = 0x829; +				break; +			} +		} +		break; + +	case gskScratchingHead: +		if (gridX > 0 && gridY > 0) { +			if (_gnapY > gridY) { +				if (_gnapX > gridX) { +					sequenceId = 0x834; +					_gnapIdleFacing = 3; +				} else { +					sequenceId = 0x885; +					_gnapIdleFacing = 7; +				} +			} else { +				if (_gnapX > gridX) { +					sequenceId = 0x834; +					_gnapIdleFacing = 3; +				} else { +					sequenceId = 0x833; +					_gnapIdleFacing = 1; +				} +			} +		} else { +			switch (_gnapIdleFacing) { +			case 1: +				sequenceId = 0x833; +				_gnapIdleFacing = 1; +				break; +			case 3: +				sequenceId = 0x834; +				_gnapIdleFacing = 3; +				break; +			case 7: +				sequenceId = 0x885; +				_gnapIdleFacing = 7; +				break; +			default: +				sequenceId = 0x834; +				_gnapIdleFacing = 3; +				break; +			} +		} +		break; + +	case gskIdle: +		if (gridX > 0 && gridY > 0) { +			if (_gnapY > gridY) { +				if (_gnapX > gridX) { +					sequenceId = 0x7BC; +					_gnapIdleFacing = 5; +				} else { +					sequenceId = 0x7BB; +					_gnapIdleFacing = 7; +				} +			} else { +				if (_gnapX > gridX) { +					sequenceId = 0x7BA; +					_gnapIdleFacing = 3; +				} else { +					sequenceId = 0x7B9; +					_gnapIdleFacing = 1; +				} +			} +		} else { +			switch (_gnapIdleFacing) { +			case 1: +				sequenceId = 0x7B9; +				break; +			case 3: +				sequenceId = 0x7BA; +				break; +			case 7: +				sequenceId = 0x7BB; +				break; +			default: +				sequenceId = 0x7BC; +				break; +			} +		} +		break; + +	case gskBrainPulsating: +		_gnapBrainPulseNum = (_gnapBrainPulseNum + 1) & 1; +		if (gridX > 0 && gridY > 0) { +			if (_gnapY > gridY) { +				if (_gnapX > gridX) { +					sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x812; +					_gnapIdleFacing = 5; +				} else { +					sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x7FE; +					_gnapIdleFacing = 7; +				} +			} else { +				if (_gnapX > gridX) { +					sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x7D6; +					_gnapIdleFacing = 3; +				} else { +					sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x7EA; +					_gnapIdleFacing = 1; +				} +			} +		} else { +			switch (_gnapIdleFacing) { +			case 1: +				sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x7EA; +				break; +			case 3: +				sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x7D6; +				break; +			case 7: +				sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x7FE; +				break; +			default: +				sequenceId = _gnapBrainPulseRndValue + _gnapBrainPulseNum + 0x812; +				break; +			} +		} +		break; + +	case gskImpossible: +		if (gridX > 0 && gridY > 0) { +			if (_gnapY > gridY) { +				if (_gnapX > gridX) { +					sequenceId = 0x831; +					_gnapIdleFacing = 3; +				} else { +					sequenceId = 0x7A8; +					_gnapIdleFacing = 1; +				} +			} else { +				if (_gnapX > gridX) { +					sequenceId = 0x831; +					_gnapIdleFacing = 3; +				} else { +					if (_gnapX % 2) +						sequenceId = 0x7A8; +					else +						sequenceId = 0x89A; +					_gnapIdleFacing = 1; +				} +			} +		} else if (_gnapIdleFacing != 1 && _gnapIdleFacing != 7) { +			sequenceId = 0x831; +			_gnapIdleFacing = 3; +		} else { +			if (_currentSceneNum % 2) +				sequenceId = 0x7A8; +			else +				sequenceId = 0x89A; +			_gnapIdleFacing = 1; +		} +		break; + +	case gskDeflect: +		if (gridX > 0 && gridY > 0) { +			if (_gnapY > gridY) { +				if (_gnapX > gridX) { +					sequenceId = 0x830; +					_gnapIdleFacing = 5; +				} else { +					sequenceId = 0x82F; +					_gnapIdleFacing = 7; +				} +			} else { +				if (_gnapX > gridX) { +					sequenceId = 0x82E; +					_gnapIdleFacing = 3; +				} else { +					sequenceId = 0x7A7; +					_gnapIdleFacing = 1; +				} +			} +		} else { +			switch (_gnapIdleFacing) { +			case 1: +				sequenceId = 0x7A7; +				break; +			case 3: +				sequenceId = 0x82E; +				break; +			case 5: +				sequenceId = 0x830; +				break; +			case 7: +				sequenceId = 0x82F; +				break; +			} +		} +		break; + +	case gskUseDevice: +		switch (_gnapIdleFacing) { +		case 1: +			sequenceId = 0x83A; +			break; +		case 3: +			sequenceId = 0x83C; +			break; +		case 5: +			sequenceId = 0x840; +			break; +		case 7: +			sequenceId = 0x83E; +			break; +		} +		break; + +	case gskMoan1: +		if (gridX > 0 && gridY > 0) { +			if (_gnapY > gridY) { +				if (_gnapX > gridX) { +					sequenceId = 0x832; +					_gnapIdleFacing = 3; +				} else { +					sequenceId = 0x7AA; +					_gnapIdleFacing = 1; +				} +			} else { +				if (_gnapX > gridX) { +					sequenceId = 0x832; +					_gnapIdleFacing = 3; +				} else { +					sequenceId = 0x7AA; +					_gnapIdleFacing = 1; +				} +			} +		} else if (_gnapIdleFacing != 1 && _gnapIdleFacing != 7) { +			sequenceId = 0x832; +			_gnapIdleFacing = 3; +		} else { +			sequenceId = 0x7AA; +			_gnapIdleFacing = 1; +		} +		break; + +	case gskMoan2: +		if (gridX > 0 && gridY > 0) { +			if (_gnapY > gridY) { +				if (_gnapX > gridX) { +					sequenceId = 0x832; +					_gnapIdleFacing = 3; +				} else { +					sequenceId = 0x7AA; +					_gnapIdleFacing = 1; +				} +			} else { +				if (_gnapX > gridX) { +					sequenceId = 0x832; +					_gnapIdleFacing = 3; +				} else { +					sequenceId = 0x7AA; +					_gnapIdleFacing = 1; +				} +			} +		} else if (_gnapIdleFacing != 1 && _gnapIdleFacing != 7) { +			sequenceId = 0x832; +			_gnapIdleFacing = 3; +		} else { +			sequenceId = 0x7AA; +			_gnapIdleFacing = 1; +		} +		break; + +	} + +	return sequenceId | 0x10000; +} + +int GnapEngine::getGnapShowSequenceId(int index, int gridX, int gridY) { + +	int sequenceId; +	int facing = _gnapIdleFacing; + +	if (gridY > 0 && gridX > 0) { +		if (_gnapY > gridY) { +			if (_gnapX > gridX) +				_gnapIdleFacing = 5; +			else +				_gnapIdleFacing = 7; +		} else { +			if (_gnapX > gridX) +				_gnapIdleFacing = 5; +			else +				_gnapIdleFacing = 7; +		} +	} else if (_gnapIdleFacing != 1 && _gnapIdleFacing != 7) { +		_gnapIdleFacing = 5; +	} else { +		_gnapIdleFacing = 7; +	} + +	switch (index) { +	case 0: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x8A0; +		else +			sequenceId = 0x8A1; +		break; +	case 1: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x880; +		else +			sequenceId = 0x895; +		break; +	case 2: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x884; +		else +			sequenceId = 0x899; +		break; +	//Skip 3 +	case 4: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x881; +		else +			sequenceId = 0x896; +		break; +	case 5: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x883; +		else +			sequenceId = 0x898; +		break; +	case 6: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x87E; +		else +			sequenceId = 0x893; +		break; +	case 7: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x848; +		else +			sequenceId = 0x890; +		break; +	case 8: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x87D; +		else +			sequenceId = 0x892; +		break; +	case 9: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x882; +		else +			sequenceId = 0x897; +		break; +	case 10: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x87C; +		else +			sequenceId = 0x891; +		break; +	case 11: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x87C; +		else +			sequenceId = 0x891; +		break; +	case 12: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x87D; +		else +			sequenceId = 0x892; +		break; +	case 13: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x888; +		else +			sequenceId = 0x89D; +		break; +	case 14: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x87F; +		else +			sequenceId = 0x894; +		break; +	case 15: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x87B; +		else +			sequenceId = 0x8A3; +		break; +	case 16: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x877; +		else +			sequenceId = 0x88C; +		break; +	//Skip 17 +	case 18: +		sequenceId = 0x887; +		break; +	case 19: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x87A; +		else +			sequenceId = 0x88F; +		break; +	case 20: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x878; +		else +			sequenceId = 0x88D; +		break; +	case 21: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x879; +		else +			sequenceId = 0x88E; +		break; +	case 22: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x88A; +		else +			sequenceId = 0x89F; +		break; +	case 23: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x889; +		else +			sequenceId = 0x89E; +		break; +	case 24: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x886; +		else +			sequenceId = 0x89B; +		break; +	case 25: +		if (_gnapIdleFacing == 7) +			sequenceId = 0x87A; +		else +			sequenceId = 0x88F; +		break; +	//Skip 26 +	//Skip 27 +	//Skip 28 +	//Skip 29 +	default: +		_gnapIdleFacing = facing; +		sequenceId = getGnapSequenceId(gskImpossible, 0, 0); +		break; +	} +	return sequenceId; +} + +void GnapEngine::gnapIdle() { +	if (_gnapSequenceId != -1 && _gnapSequenceDatNum == 1 && +		(_gnapSequenceId == 0x7A6 || _gnapSequenceId == 0x7AA || +		_gnapSequenceId == 0x832 || _gnapSequenceId == 0x841 || +		_gnapSequenceId == 0x842 || _gnapSequenceId == 0x8A2 || +		_gnapSequenceId == 0x833 || _gnapSequenceId == 0x834 || +		_gnapSequenceId == 0x885 || _gnapSequenceId == 0x7A8 || +		_gnapSequenceId == 0x831 || _gnapSequenceId == 0x89A)) { +		_gameSys->insertSequence(getGnapSequenceId(gskIdle, 0, 0) | 0x10000, _gnapId, +			makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +			32, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +		_gnapSequenceId = getGnapSequenceId(gskIdle, 0, 0); +		_gnapSequenceDatNum = 1; +	} +} + +void GnapEngine::gnapActionIdle(int sequenceId) { +	if (_gnapSequenceId != -1 && ridToDatIndex(sequenceId) == _gnapSequenceDatNum && +		ridToEntryIndex(sequenceId) == _gnapSequenceId) { +		_gameSys->insertSequence(getGnapSequenceId(gskIdle, 0, 0) | 0x10000, _gnapId, +			makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +			32, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +		_gnapSequenceId = getGnapSequenceId(gskIdle, 0, 0); +		_gnapSequenceDatNum = 1; +	} +} + +void GnapEngine::playGnapSequence(int sequenceId) { +	_timers[2] = getRandom(30) + 20; +	_timers[3] = 300; +	gnapIdle(); +	_gameSys->insertSequence(sequenceId, _gnapId, +		makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +		9, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +	_gnapSequenceId = ridToEntryIndex(sequenceId); +	_gnapSequenceDatNum = ridToDatIndex(sequenceId); +} + +void GnapEngine::playGnapImpossible(int gridX, int gridY) { +	playGnapSequence(getGnapSequenceId(gskImpossible, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapScratchingHead(int gridX, int gridY) { +	playGnapSequence(getGnapSequenceId(gskScratchingHead, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapMoan1(int gridX, int gridY) { +	playGnapSequence(getGnapSequenceId(gskMoan1, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapMoan2(int gridX, int gridY) { +	playGnapSequence(getGnapSequenceId(gskMoan2, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapBrainPulsating(int gridX, int gridY) { +	playGnapSequence(getGnapSequenceId(gskBrainPulsating, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapPullOutDevice(int gridX, int gridY) { +	playGnapSequence(getGnapSequenceId(gskPullOutDevice, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapPullOutDeviceNonWorking(int gridX, int gridY) { +	playGnapSequence(getGnapSequenceId(gskPullOutDeviceNonWorking, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapUseDevice(int gridX, int gridY) { +	playGnapSequence(getGnapSequenceId(gskUseDevice, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapIdle(int gridX, int gridY) { +	playGnapSequence(getGnapSequenceId(gskIdle, gridX, gridY) | 0x10000); +} + +void GnapEngine::playGnapShowItem(int itemIndex, int gridLookX, int gridLookY) { +	playGnapSequence(getGnapShowSequenceId(itemIndex, gridLookX, gridLookY) | 0x10000); +} + +void GnapEngine::playGnapShowCurrItem(int gridX, int gridY, int gridLookX, int gridLookY) { +	if (_platX == gridX && _platY == gridY) +		beaverMakeRoom(); +	gnapWalkTo(gridX, gridY, -1, -1, 1); +	playGnapShowItem(_grabCursorSpriteIndex, gridLookX, gridLookY); +} + +void GnapEngine::updateGnapIdleSequence() { +	if (_gnapActionStatus < 0) { +		if (_timers[2] > 0) { +			if (_timers[3] == 0) { +				_timers[2] = 60; +				_timers[3] = 300; +				_gnapRandomValue = getRandom(5); +				if (_gnapIdleFacing == 1) { +					switch (_gnapRandomValue) { +					case 0: +						playGnapSequence(0x107A6); +						break; +					case 1: +						playGnapSequence(0x107AA); +						break; +					case 2: +						playGnapSequence(0x10841); +						break; +					default: +						playGnapSequence(0x108A2); +						break; +					} +				} else if (_gnapIdleFacing == 3) { +					if (_gnapRandomValue > 2) +						playGnapSequence(0x10832); +					else +						playGnapSequence(0x10842); +				} +			} +		} else { +			_timers[2] = getRandom(30) + 20; +			if (_gnapIdleFacing == 1) { +				_gameSys->insertSequence(0x107BD, _gnapId, +					makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +					8, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +				_gnapSequenceId = 0x7BD; +				_gnapSequenceDatNum = 1; +			} else if (_gnapIdleFacing == 3) { +				_gameSys->insertSequence(0x107BE, _gnapId, +					makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +					8, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +				_gnapSequenceId = 0x7BE; +				_gnapSequenceDatNum = 1; +			} +		} +	} else { +		_timers[2] = getRandom(30) + 20; +		_timers[3] = 300; +	} +} + +void GnapEngine::updateGnapIdleSequence2() { +	if (_gnapActionStatus < 0) { +		if (_timers[2] > 0) { +			if (_timers[3] == 0) { +				_timers[2] = 60; +				_timers[3] = 300; +				if (_gnapIdleFacing == 1) { +					playGnapSequence(0x107AA); +				} else if (_gnapIdleFacing == 3) { +					playGnapSequence(0x10832); +				} +			} +		} else { +			_timers[2] = getRandom(30) + 20; +			if (_gnapIdleFacing == 1) { +				_gameSys->insertSequence(0x107BD, _gnapId, +					makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +					8, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +				_gnapSequenceId = 0x7BD; +				_gnapSequenceDatNum = 1; +			} else if (_gnapIdleFacing == 3) { +				_gameSys->insertSequence(0x107BE, _gnapId, +					makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +					8, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +				_gnapSequenceId = 0x7BE; +				_gnapSequenceDatNum = 1; +			} +		} +	} else { +		_timers[2] = getRandom(30) + 20; +		_timers[3] = 300; +	} +} + +bool GnapEngine::testWalk(int animationIndex, int someStatus, int gridX1, int gridY1, int gridX2, int gridY2) { +	if (_mouseClickState.left && someStatus == _gnapActionStatus) { +		_isLeavingScene = false; +		_gameSys->setAnimation(0, 0, animationIndex); +		_gnapActionStatus = -1; +		_beaverActionStatus = -1; +		gnapWalkTo(gridX1, gridY1, -1, -1, 1); +		platypusWalkTo(gridX2, gridY2, -1, -1, 1); +		_mouseClickState.left = false; +		return true; +	} +	return false; +} + +void GnapEngine::initGnapPos(int gridX, int gridY, int facing) { +	_timers[2] = 30; +	_timers[3] = 300; +	_gnapX = gridX; +	_gnapY = gridY; +	if (facing <= 0) +		_gnapIdleFacing = 1; +	else +		_gnapIdleFacing = facing; +	if (_gnapIdleFacing == 3) { +		_gnapSequenceId = 0x7B8; +  	} else { +		_gnapSequenceId = 0x7B5; +		_gnapIdleFacing = 1; +	} +	_gnapId = 20 * _gnapY; +	_gnapSequenceDatNum = 1; +	_gameSys->insertSequence(makeRid(1, _gnapSequenceId), 20 * _gnapY, +		0, 0, +		1, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +} + +void GnapEngine::gnapInitBrainPulseRndValue() { +	_gnapBrainPulseRndValue = 2 * getRandom(10); +} + +void GnapEngine::gnapUseDeviceOnBeaver() { +	 +	playGnapSequence(makeRid(1, getGnapSequenceId(gskPullOutDevice, _platX, _platY))); + +	if (_beaverFacing != 0) { +		_gameSys->insertSequence(makeRid(1, 0x7D5), _beaverId, +			makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId, +			8, 0, 75 * _platX - _platGridX, 48 * _platY - _platGridY); +		_beaverSequenceId = 0x7D5; +		_beaverSequenceDatNum = 1; +	} else { +		_gameSys->insertSequence(makeRid(1, 0x7D4), _beaverId, +			makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId, +			8, 0, 75 * _platX - _platGridX, 48 * _platY - _platGridY); +		_beaverSequenceId = 0x7D4; +		_beaverSequenceDatNum = 1; +	} + +	int newSequenceId = getGnapSequenceId(gskUseDevice, 0, 0); +	_gameSys->insertSequence(makeRid(1, newSequenceId), _gnapId, +		makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +		8, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +	_gnapSequenceId = newSequenceId; +	_gnapSequenceDatNum = 1; + +} + +void GnapEngine::doCallback(int callback) { +	switch (callback) { +	case 8: +		scene08_updateAnimationsCb(); +		break; +	case 10: +		scene10_updateAnimationsCb(); +		break; +	case 20: +		scene20_updateAnimationsCb(); +		break; +	} +} + +bool GnapEngine::gnapPlatypusAction(int gridX, int gridY, int platSequenceId, int callback) { +	bool result = false; +	 +	if (_gnapActionStatus <= -1 && _beaverActionStatus <= -1) { +		_gnapActionStatus = 100; +		if (isPointBlocked(_platX + gridX, _platY + gridY) && (_platX + gridX != _gnapX || _platY + gridY != _gnapY)) +			platypusWalkStep(); +		if (!isPointBlocked(_platX + gridX, _platY + gridY) && (_platX + gridX != _gnapX || _platY + gridY != _gnapY)) { +			gnapWalkTo(_platX + gridX, _platY + gridY, 0, 0x107B9, 1); +			while (_gameSys->getAnimationStatus(0) != 2) { +				updateMouseCursor(); +				doCallback(callback); +				gameUpdateTick(); +			} +			_gameSys->setAnimation(0, 0, 0); +			if (_platX + gridX == _gnapX && _platY + gridY == _gnapY) { +				_gameSys->setAnimation(platSequenceId, _beaverId, 1); +				playBeaverSequence(platSequenceId); +				while (_gameSys->getAnimationStatus(1) != 2) { +					updateMouseCursor(); +					doCallback(callback); +					gameUpdateTick(); +				} +				result = true; +			} +		} +		_gnapActionStatus = -1; +	} +	return result; +} + +void GnapEngine::gnapKissPlatypus(int callback) { +	if (gnapPlatypusAction(-1, 0, 0x107D1, callback)) { +		_gnapActionStatus = 100; +		_gameSys->setAnimation(0, 0, 1); +		_gameSys->setAnimation(0x10847, _gnapId, 0); +		_gameSys->insertSequence(0x10847, _gnapId, +			makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +			8, 0, 15 * (5 * _gnapX - 20) - (21 - _gridMinX), 48 * (_gnapY - 6) - (146 - _gridMinY)); +		_gnapSequenceDatNum = 1; +		_gnapSequenceId = 0x847; +		_gameSys->insertSequence(0x107CB, _beaverId, +			makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId, +			8, getSequenceTotalDuration(0x10847), 75 * _platX - _platGridX, 48 * _platY - _platGridY); +		_beaverSequenceDatNum = 1; +		_beaverSequenceId = 0x7CB; +		_beaverFacing = 0; +		playGnapSequence(0x107B5); +		while (_gameSys->getAnimationStatus(0) != 2) { +			updateMouseCursor(); +			doCallback(callback); +			gameUpdateTick(); +		} +		_gameSys->setAnimation(0, 0, 0); +		_gnapActionStatus = -1; +	} else { +		playGnapSequence(getGnapSequenceId(gskScratchingHead, _platX, _platY) | 0x10000); +	} +} + +void GnapEngine::gnapUseJointOnPlatypus() { +	setGrabCursorSprite(-1); +	if (gnapPlatypusAction(1, 0, 0x107C1, 0)) { +		_gnapActionStatus = 100; +		_gameSys->setAnimation(0, 0, 1); +		_gameSys->setAnimation(0x10876, _beaverId, 0); +		_gameSys->insertSequence(0x10875, _gnapId, +			makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +			8, 0, 15 * (5 * _gnapX - 30), 48 * (_gnapY - 7)); +		_gnapSequenceDatNum = 1; +		_gnapSequenceId = 0x875; +		_gameSys->insertSequence(0x10876, _beaverId, +			_beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, +			8, 0, 15 * (5 * _platX - 25), 48 * (_platY - 7)); +		_beaverSequenceDatNum = 1; +		_beaverSequenceId = 0x876; +		_beaverFacing = 0; +		playGnapSequence(0x107B5); +		gnapWalkStep(); +		while (_gameSys->getAnimationStatus(0) != 2) { +			updateMouseCursor(); +			gameUpdateTick(); +		} +		_gameSys->setAnimation(0, 0, 0); +		_gnapActionStatus = -1; +	} else { +		playGnapSequence(getGnapSequenceId(gskScratchingHead, _platX, _platY) | 0x10000); +	} +} + +void GnapEngine::gnapUseDisguiseOnPlatypus() { +	_gameSys->setAnimation(0x10846, _gnapId, 0); +	playGnapSequence(0x10846); +	while (_gameSys->getAnimationStatus(0) != 2) +		gameUpdateTick(); +	_newSceneNum = 47; +	_isLeavingScene = true; +	_sceneDone = true; +	setFlag(10); +} + +int GnapEngine::getBeaverSequenceId(int kind, int gridX, int gridY) { +	int sequenceId; + +	// TODO kind is always 0, remove that parameter +	if (kind != 0) +		return 0; + +	if (gridX > 0 && gridY > 0) { +		if (gridX < _platX) { +			sequenceId = 0x7CC; +			_beaverFacing = 4; +		} else { +			sequenceId = 0x7CB; +			_beaverFacing = 0; +		} +	} else if (_beaverFacing != 0) { +		sequenceId = 0x7CC; +		_beaverFacing = 4; +	} else { +		sequenceId = 0x7CB; +		_beaverFacing = 0; +	} +	return sequenceId | 0x10000; +} + +void GnapEngine::playBeaverSequence(int sequenceId) { +	_gameSys->insertSequence(sequenceId, _beaverId, +		makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId, +		9, 0, 75 * _platX - _platGridX, 48 * _platY - _platGridY); +	_beaverSequenceId = ridToEntryIndex(sequenceId); +	_beaverSequenceDatNum = ridToDatIndex(sequenceId); +} + +void GnapEngine::updateBeaverIdleSequence() { +	if (_beaverActionStatus < 0 && _gnapActionStatus < 0) { +		if (_timers[0] > 0) { +			if (_timers[1] == 0) { +				_timers[1] = getRandom(20) + 30; +				_gnapRandomValue = getRandom(10); +				if (_beaverFacing != 0) { +					if (_gnapRandomValue != 0 || _beaverSequenceId != 0x7CA) { +						if (_gnapRandomValue != 1 || _beaverSequenceId != 0x7CA) +							playBeaverSequence(0x107CA); +						else +							playBeaverSequence(0x10845); +					} else { +						playBeaverSequence(0x107CC); +					} +				} else if (_gnapRandomValue != 0 || _beaverSequenceId != 0x7C9) { +					if (_gnapRandomValue != 1 || _beaverSequenceId != 0x7C9) { +						if (_gnapRandomValue != 2 || _beaverSequenceId != 0x7C9) +							playBeaverSequence(0x107C9); +						else +							playBeaverSequence(0x108A4); +					} else { +						playBeaverSequence(0x10844); +					} +				} else { +					playBeaverSequence(0x107CB); +				} +			} +		} else { +			_timers[0] = getRandom(75) + 75; +			beaverMakeRoom(); +		} +	} else { +		_timers[0] = 100; +		_timers[1] = 35; +	} +} + +void GnapEngine::beaverSub426234() { +	if (_beaverActionStatus < 0 && _gnapActionStatus < 0) { +		if (_timers[0]) { +			if (!_timers[1]) { +				_timers[1] = getRandom(20) + 30; +				_gnapRandomValue = getRandom(10); +				if (_beaverFacing != 0) { +					if (_gnapRandomValue >= 2 || _beaverSequenceId != 0x7CA) +						playBeaverSequence(0x107CA); +					else +						playBeaverSequence(0x107CC); +				} else { +					if (_gnapRandomValue >= 2 || _beaverSequenceId != 0x7C9) { +						playBeaverSequence(0x107C9); +					} else { +						playBeaverSequence(0x107CB); +					} +				} +			} +		} else { +			_timers[0] = getRandom(75) + 75; +			beaverMakeRoom(); +		} +	} else { +		_timers[0] = 100; +		_timers[1] = 35; +	} +} + +void GnapEngine::initBeaverPos(int gridX, int gridY, int facing) { +	_timers[0] = 50; +	_timers[1] = 20; +	_platX = gridX; +	_platY = gridY; +	if (facing <= 0) +		_beaverFacing = 0; +	else +		_beaverFacing = facing; +	if (_beaverFacing == 4) { +		_beaverSequenceId = 0x7D1; +	} else { +		_beaverSequenceId = 0x7C1; +		_beaverFacing = 0; +	} +	_beaverId = 20 * _platY; +	_beaverSequenceDatNum = 1; +	_gameSys->insertSequence(makeRid(1, _beaverSequenceId), 20 * _platY, +		0, 0, +		1, 0, 75 * _platX - _platGridX, 48 * _platY - _platGridY); +} + +//////////////////////////////////////////////////////////////////////////////// + +void GnapEngine::initGlobalSceneVars() { + +	// Scene 1 +	_s01_pigsIdCtr = 0; +	_s01_smokeIdCtr = 0; +	_s01_spaceshipSurface = 0; +	 +	// Scene 2 +	_s02_truckGrillCtr = 0; +	 +	// Scene 3 +	_s03_nextPlatSequenceId = -1; +	_s03_platypusScared = false; +	_s03_platypusHypnotized = false; +	 +	// Scene 4 +	_s04_dogIdCtr = 0; +	//_s04_triedWindow = true;//?? +	_s04_triedWindow = false; +	 +	// Scene 5 +	_s05_nextChickenSequenceId = -1; +	 +	// Scene 6 +	_s06_nextPlatSequenceId = -1; +	 +	// Scene 11 +	_s11_billardBallCtr = 0; +	 +	// Scene 13 +	_s13_backToiletCtr = -1; +	 +	// Scene 17 +	_s17_platTryGetWrenchCtr = 0; +	_s17_wrenchCtr = 2; +	_s17_nextCarWindowSequenceId = -1; +	_s17_nextWrenchSequenceId = -1; +	_s17_canTryGetWrench = true; +	_s17_platPhoneCtr = 0; +	_s17_nextPhoneSequenceId = -1; +	_s17_currPhoneSequenceId = -1; +	 +	// Scene 18 +	_s18_garbageCanPos = 8; +	_s18_platPhoneCtr = 0; +	_s18_platPhoneIter = 0; +	_s18_nextPhoneSequenceId = -1; +	_s18_currPhoneSequenceId = -1; +	 +	// Scene 19 +	_s19_toyGrabCtr = 0; +	_s19_pictureSurface = 0; +	_s19_shopAssistantCtr = 0; + +	// Scene 20 +	_s20_stonerGuyCtr = 3; +	_s20_stonerGuyShowingJoint = false; +	_s20_groceryStoreGuyCtr = 0; +	 +	// Scene 22 +	_s22_caughtBefore = false; +	_s22_cashierCtr = 3; + +	// Scene 50 +	_s50_timesPlayed = 0; +	_s50_timesPlayedModifier = 0; +	_s50_attackCounter = 0; +	_s50_leftTongueEnergyBarPos = 10; +	_s50_leftTongueNextIdCtr = 0; +	_s50_rightTongueEnergyBarPos = 10; +	_s50_rightTongueNextIdCtr = 0; +	 +	// Scene 52 +	_s52_gameScore = 0; +	_s52_aliensInitialized = false; +	_s52_alienDirection = 0; +	_s52_soundToggle = false; +	 +	// Scene 53 +	_s53_callsMadeCtr = 0; +	_s53_callsRndUsed = 0; + +	// Toy UFO +	_toyUfoId = 0; +	_toyUfoActionStatus = -1; +	_toyUfoX = 0; +	_toyUfoY = 50; + +} + +bool GnapEngine::sceneXX_sub_4466B1() { + +	if (isKeyStatus1(Common::KEYCODE_ESCAPE)) { +		clearKeyStatus1(Common::KEYCODE_ESCAPE); +		clearKeyStatus1(Common::KEYCODE_UP); +		clearKeyStatus1(Common::KEYCODE_RIGHT); +		clearKeyStatus1(Common::KEYCODE_LEFT); +		clearKeyStatus1(Common::KEYCODE_p); +		return true; +	} + +	if (isKeyStatus1(Common::KEYCODE_p)) { +		clearKeyStatus1(Common::KEYCODE_p); +		pauseGame(); +		updatePause(); +	} +	return false; + +} + +void GnapEngine::sceneXX_playRandomSound(int timerIndex) { +	if (!_timers[timerIndex]) { +		_timers[timerIndex] = getRandom(40) + 50; +		_gnapRandomValue = getRandom(4); +		switch (_gnapRandomValue) { +		case 0: +			playSound(0x1091B, 0); +			break; +		case 1: +			playSound(0x10921, 0); +			break; +		case 2: +			playSound(0x10927, 0); +			break; +		case 3: +			playSound(0x1091D, 0); +			break; +		} +	} +} + +void GnapEngine::playSequences(int fullScreenSpriteId, int sequenceId1, int sequenceId2, int sequenceId3) { +	setGrabCursorSprite(-1); +	_gameSys->setAnimation(sequenceId2, _gnapId, 0); +	_gameSys->insertSequence(sequenceId2, _gnapId, +		makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +		8, 0, 15 * (5 * _gnapX - 25), 48 * (_gnapY - 8)); +	_gnapSequenceId = sequenceId2; +	_gnapSequenceDatNum = 0; +	while (_gameSys->getAnimationStatus(0) != 2) +		gameUpdateTick(); +	hideCursor(); +	addFullScreenSprite(fullScreenSpriteId, 255); +	_gameSys->setAnimation(sequenceId1, 256, 0); +	_gameSys->insertSequence(sequenceId1, 256, 0, 0, kSeqNone, 0, 0, 0); +	while (_gameSys->getAnimationStatus(0) != 2) +		gameUpdateTick(); +	_gameSys->setAnimation(sequenceId3, _gnapId, 0); +	_gameSys->insertSequence(sequenceId3, _gnapId, +		makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +		8, 0, 15 * (5 * _gnapX - 25), 48 * (_gnapY - 8)); +	removeFullScreenSprite(); +	showCursor(); +	_gnapSequenceId = sequenceId3; +} + +// Scene 0 + +int GnapEngine::scene00_init() { +	return 0x37C; +} + +void GnapEngine::toyUfoSetStatus(int a1) { +	clearFlag(16); +	clearFlag(17); +	clearFlag(18); +	clearFlag(19); +	setFlag(a1); +} + +int GnapEngine::toyUfoGetSequenceId() { +	if (isFlag(16)) +		return 0x84E; +	if (isFlag(17)) +		return 0x84B; +	if (isFlag(18)) +		return 0x84D; +	if (isFlag(19)) +		return 0x84C; +	return 0x84E; +} + +bool GnapEngine::toyUfoCheckTimer() { +	if (!isFlag(12) || isFlag(18) || _timers[9] || +		_toyUfoSequenceId == 0x870 || _toyUfoSequenceId == 0x871 || _toyUfoSequenceId == 0x872 || _toyUfoSequenceId == 0x873) +		return false; +	_sceneDone = true; +	_newSceneNum = 41; +	return true; +} + +void GnapEngine::toyUfoFlyTo(int destX, int destY, int a3, int a4, int a5, int a6, int animationIndex) { +	int v21 = 0; +	int v14 = 0; +	int v17 = 36; +	int v15 = 32; +	int i = 0; +	GridStruct v16[34]; +	 +	if (destX == -1) +		destX = _leftClickMouseX; +	 +	if (destY == -1) +		destY = _leftClickMouseY; + +	//CHECKME +	 +	int v25 = CLIP(destX, a3, a4); +	int v26 = CLIP(destY, a5, a6); +	int v24, v23; +	int v13, v20; + +	if (v25 == _toyUfoX) +		v24 = 0; +	else +		v24 = (v25 - _toyUfoX) / ABS(v25 - _toyUfoX); +	 +	if (v26 == _toyUfoY) +		v23 = 0; +	else +		v23 = (v26 - _toyUfoY) / ABS(v26 - _toyUfoY); +	 +	v13 = ABS(v25 - _toyUfoX); +	v20 = ABS(v26 - _toyUfoY); +	 +	if (v20 > v13) { +		int v22 = v20 / v15; +		while (v14 < v20 && i < 34) { +			if (v22 - 5 >= i) { +				v15 = MIN(36, 8 * i + 8); +			} else { +				v15 = MAX(6, v15 - 3); +			} +			v14 += v15; +			v16[i].gridX1 = _toyUfoX + v24 * v13 * v14 / v20; +			v16[i].gridY1 = _toyUfoY + v23 * v14; +			++i; +		} +	} else { +		int v22 = v13 / v17; +		while (v14 < v13 && i < 34) { +			if (v22 - 5 >= i) { +				v17 = MIN(38, 8 * i + 8); +			} else { +				v17 = MAX(6, v17 - 3); +			} +			v14 += v17; +			v16[i].gridX1 = _toyUfoX + v24 * v14; +			v16[i].gridY1 = _toyUfoY + v23 * v20 * v14 / v13; +			++i; +		} +	} + +	v21 = i - 1; +	 +	_toyUfoX = v25; +	_toyUfoY = v26; +	 +	debug("v21: %d", v21); +	 +	if (i - 1 > 0) { +		int v18; +		if (isFlag(16)) +			v18 = 0x867; +		else if (isFlag(17)) +			v18 = 0x84F; +		else if (isFlag(18)) +			v18 = 0x85F; +		else if (isFlag(19)) +			v18 = 0x857; +		v16[0].sequenceId = v18; +		v16[0].id = 0; +		_gameSys->insertSequence(v18 | 0x10000, 0, +			_toyUfoSequenceId | 0x10000, _toyUfoId, +			8, 0, v16[0].gridX1 - 365, v16[0].gridY1 - 128); +		for (i = 1; i < v21; ++i) { +			v16[i].sequenceId = v18 + (i % 8); +			v16[i].id = i; +			_gameSys->insertSequence(v16[i].sequenceId | 0x10000, v16[i].id, +				v16[i - 1].sequenceId | 0x10000, v16[i - 1].id, +				8, 0, +				v16[i].gridX1 - 365, v16[i].gridY1 - 128); +		} +	 +		_toyUfoSequenceId = v16[v21 - 1].sequenceId; +		_toyUfoId = v16[v21 - 1].id; +	 +		if (animationIndex >= 0) +			_gameSys->setAnimation(_toyUfoSequenceId | 0x10000, _toyUfoId, animationIndex); +	 +	} + +} + +// Scene 99 + +int GnapEngine::cutscene_init() { +	return -1; +} + +void GnapEngine::cutscene_run() { +	 +	int itemIndex = 0; +	int soundId = -1; +	int volume = 100; +	int duration = 0; +	bool skip = false; + +	int v1 = 0; + +	if (_prevSceneNum == 2) { +		soundId = 0x36B; +		duration = MAX(1, 300 / getSequenceTotalDuration(_s99_dword_47F370[_s99_itemsCount - 1]));//CHECKME +		_timers[0] = 0; +	} + +	if (soundId != -1) +		playSound(soundId, 0); + +	hideCursor(); + +	_gameSys->drawSpriteToBackground(0, 0, _s99_dword_47F2F0[0]); + +	for (int j = 0; j < _s99_dword_47F330[0]; ++j) +		_gameSys->insertSequence(_s99_dword_47F370[j], j + 2, 0, 0, kSeqNone, 0, 0, 0); +	_gameSys->setAnimation(_s99_dword_47F370[0], 2, 0); +		 +	clearKeyStatus1(Common::KEYCODE_ESCAPE); +	clearKeyStatus1(Common::KEYCODE_SPACE); +	clearKeyStatus1(29); + +	_mouseClickState.left = false; +	 +	while (!_sceneDone) { + +		gameUpdateTick(); + +		if (_gameSys->getAnimationStatus(0) == 2 || skip) { +			skip = 0; +			_gameSys->requestClear2(0); +			_gameSys->requestClear1(); +			_gameSys->setAnimation(0, 0, 0); +			v1 += _s99_dword_47F330[itemIndex++]; +			if (itemIndex >= _s99_itemsCount) { +				_sceneDone = true; +			} else { +				for (int m = 0; m < _s99_dword_47F330[itemIndex]; ++m) +					_gameSys->insertSequence(_s99_dword_47F370[v1 + m], m + 2, 0, 0, kSeqNone, 0, 0, 0); +				_gameSys->drawSpriteToBackground(0, 0, _s99_dword_47F2F0[itemIndex]); +				_gameSys->setAnimation(_s99_dword_47F370[v1], 2, 0); +			} +		} + +		if (isKeyStatus1(Common::KEYCODE_ESCAPE) || isKeyStatus1(Common::KEYCODE_SPACE) || isKeyStatus1(29)) { +			clearKeyStatus1(Common::KEYCODE_ESCAPE); +			clearKeyStatus1(Common::KEYCODE_SPACE); +			clearKeyStatus1(29); +			if (_s99_canSkip[itemIndex] & 1) +				skip = true; +			else +				_sceneDone = true; +		} + +		if (!_timers[0] && itemIndex == _s99_itemsCount - 1) { +			_timers[0] = 2; +			volume = MAX(1, volume - duration); +			setSoundVolume(soundId, volume); +		} +		 +	} + +	if (soundId != -1) +		stopSound(soundId); +	 +} + +} // End of namespace Gnap diff --git a/engines/gnap/gnap.h b/engines/gnap/gnap.h new file mode 100644 index 0000000000..e1d13eca41 --- /dev/null +++ b/engines/gnap/gnap.h @@ -0,0 +1,1117 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef GNAP_H +#define GNAP_H + +#include "common/array.h" +#include "common/events.h" +#include "common/file.h" +#include "common/memstream.h" +#include "common/random.h" +#include "common/str.h" +#include "common/substream.h" +#include "common/system.h" +#include "common/winexe.h" +#include "common/winexe_pe.h" +#include "engines/engine.h" +#include "graphics/pixelformat.h" +#include "graphics/wincursor.h" + +#include "gnap/resource.h" + +struct ADGameDescription; + +namespace Gnap { + +class DatManager; +class SequenceResource; +class SpriteResource; +class GameSys; +class SoundMan; + +struct MouseButtonState { +	bool left; +	bool right; +	bool middle; +	MouseButtonState() : left(false), right(false), middle(false) { +	} +}; + +struct Hotspot { +	int16 x1, y1, x2, y2; +	int16 field_10; +	int16 field_12; +	uint16 flags; +	int id; +	bool isPointInside(int16 x, int16 y) const { +		return x >= x1 && x <= x2 && y >= y1 && y <= y2; +	} +	bool isFlag(uint16 flag) const { +		return (flags & flag) != 0; +	} +}; + +struct GridStruct { +	int deltaX, deltaY; +	int gridX1, gridY1; +	int sequenceId; +	int id; +}; + +const int kMaxGridStructs = 30; +const int kMaxTimers = 10; + +enum { +	SF_LOOK_CURSOR		= 0x0001, +	SF_GRAB_CURSOR		= 0x0002, +	SF_TALK_CURSOR		= 0x0004, +	SF_PLAT_CURSOR		= 0x0008, +	SF_DISABLED			= 0x0010, +	SF_WALKABLE			= 0x0020, +	SF_EXIT_L_CURSOR	= 0x0040, +	SF_EXIT_R_CURSOR	= 0x0080, +	SF_EXIT_U_CURSOR	= 0x0100, +	SF_EXIT_D_CURSOR	= 0x0200, +	SF_EXIT_NW_CURSOR	= 0x0400, +	SF_EXIT_NE_CURSOR	= 0x0800, +	SF_EXIT_SW_CURSOR	= 0x1000, +	SF_EXIT_SE_CURSOR	= 0x2000 +}; + +enum { +	LOOK_CURSOR		= 0, +	GRAB_CURSOR		= 1, +	TALK_CURSOR		= 2, +	PLAT_CURSOR		= 3, +	NOLOOK_CURSOR	= 4, +	NOGRAB_CURSOR	= 5, +	NOTALK_CURSOR	= 6, +	NOPLAT_CURSOR	= 7, +	EXIT_L_CURSOR	= 8, +	EXIT_R_CURSOR	= 9, +	EXIT_U_CURSOR	= 10, +	EXIT_D_CURSOR	= 11, +	EXIT_NE_CURSOR	= 12, +	EXIT_NW_CURSOR	= 13, +	EXIT_SE_CURSOR	= 14, +	EXIT_SW_CURSOR	= 15, +	WAIT_CURSOR		= 16 +}; + +enum { +	gskPullOutDevice			= 0, +	gskPullOutDeviceNonWorking	= 1, +	gskIdle						= 2, +	gskBrainPulsating			= 3, +	gskImpossible				= 4, +	gskScratchingHead			= 5, +	gskDeflect					= 6, +	gskUseDevice				= 7, +	gskMoan1					= 8, +	gskMoan2					= 9 +}; + +enum { +	kItemMagazine			= 0, +	kItemMud				= 1, +	kItemGrass				= 2, +	kItemDisguise			= 3, +	kItemNeedle				= 4, +	kItemTwig				= 5, +	kItemGas				= 6, +	kItemKeys				= 7, +	kItemDice				= 8, +	kItemTongs				= 9, +	kItemQuarter			= 10, +	kItemQuarterWithHole	= 11, +	kItemDiceQuarterHole	= 12, +	kItemWrench				= 13, +	kItemCowboyHat			= 14, +	kItemGroceryStoreHat	= 15, +	kItemBanana				= 16, +	kItemTickets			= 17, +	kItemPicture			= 18, +	kItemEmptyBucket		= 19, +	kItemBucketWithBeer		= 20, +	kItemBucketWithPill		= 21, +	kItemPill				= 22, +	kItemHorn				= 23, +	kItemJoint				= 24, +	kItemChickenBucket		= 25, +	kItemGum				= 26, +	kItemSpring				= 27, +	kItemLightbulb			= 28, +	kItemCereals			= 29 +}; + +enum { +	kGFPlatypus				= 0, +	kGFMudTaken				= 1, +	 +	 +	kGFEnd +}; + +/* +	Game flags +		0	1			With Platypus +		1	2			Mud taken +		2	4			Needle taken +		3	8			Twig taken +		4	0x10 +		5	0x20		Keys taken +		6	0x40		Grass taken +		7	0x80		Barn padlock open +		8	0x100		Truck filled with gas +		9	0x200		Truck keys used +		10	0x400		Platypus disguised +		11	0x800		Scene flag 1 +		12	0x1000		Gnap controls toy ufo +		13	0x2000 +		14	0x4000 +		15	0x8000		Spring taken +		16	0x10000 +		17	0x20000		Joint taken +		18	0x40000 +		19	0x80000		Grocery store hat taken +		20	0x100000	Picture taken +		21	0x200000 +		22	0x400000 +		23	0x800000 +		24	0x1000000 +		25	0x2000000 +		26	0x4000000	Platypus talking with toy shop assistant +		27	0x8000000 +		28	0x10000000 +		29	0x20000000	Gas taken +		30	0x40000000 +		31	0x80000000 + + +*/ + +	// 0x7AB	Gnap walks to the right 1 +	// 0x7AC	Gnap walks to the right 2 +	// 0x7AF	Gnap walks to the left 1 +	// 0x7B0	Gnap walks to the left 2 + +struct Scene49Obstacle { +	int currSequenceId; +	int closerSequenceId; +	int passedSequenceId; +	int splashSequenceId; +	int collisionSequenceId; +	int prevId; +	int currId; +	int laneNum; +}; + +struct Scene51Item { +	int currSequenceId; +	int droppedSequenceId; +	int x, y; +	int collisionX; +	int canCatch; +	int isCollision; +	int x2; +	int id; +}; + +class GnapEngine : public Engine { +protected: +	Common::Error run(); +	virtual bool hasFeature(EngineFeature f) const; +public: +	GnapEngine(OSystem *syst, const ADGameDescription *gd); +	~GnapEngine(); +private: +	const ADGameDescription *_gameDescription; +	Graphics::PixelFormat _pixelFormat; +public:	 +	Common::RandomSource *_random; +	 +	Common::PEResources *_exe; +	 +	DatManager *_dat; +	SpriteCache *_spriteCache; +	SoundCache *_soundCache; +	SequenceCache *_sequenceCache; +	GameSys *_gameSys; +	SoundMan *_soundMan; +	 +	int _lastUpdateClock; +	 +	int _debugLevel; +	bool _gameDone; +	 +	byte _keyPressState[512]; +	byte _keyDownState[512]; +	 +	bool _isPaused; +	Graphics::Surface *_pauseSprite; +	int _timers[kMaxTimers], _savedTimers[kMaxTimers]; +	 +	MouseButtonState _mouseButtonState; +	MouseButtonState _mouseClickState; +	 +	uint32 _keyStatus1[2]; +	 +	bool _sceneSavegameLoaded, _wasSavegameLoaded; +	 +	Graphics::Surface *_backgroundSurface; +	int _prevSceneNum, _currentSceneNum, _newSceneNum;	 +	bool _sceneDone, _sceneWaiting; + +	uint32 _inventory, _gameFlags; +	 +	Hotspot _hotspots[20]; +	Common::Point _hotspotsWalkPos[20]; +	int _hotspotsCount; +	int _sceneClickedHotspot; +	 +	bool _isWaiting; +	bool _isLeavingScene; +	 +	bool _isStockDatLoaded; + +	int _newCursorValue, _cursorValue; + +	int _verbCursor, _cursorIndex; +	int _mouseX, _mouseY; +	int _leftClickMouseX, _leftClickMouseY; +	 +	Graphics::Surface *_grabCursorSprite; +	int _currGrabCursorX, _currGrabCursorY; +	int _grabCursorSpriteIndex, _newGrabCursorSpriteIndex; +	 +	Graphics::Surface *_fullScreenSprite; +	int _fullScreenSpriteId; +	 +	int _deviceX1, _deviceY1, _deviceX2, _deviceY2; +	 +	int _soundTimerIndexA; +	int _soundTimerIndexB; +	int _soundTimerIndexC; +	int _idleTimerIndex; +	 +	void updateEvents(); +	void gameUpdateTick(); +	void saveTimers(); +	void restoreTimers(); +	 +	void pauseGame(); +	void resumeGame(); +	void updatePause(); +	 +	int getRandom(int max); +	 +	int readSavegameDescription(int savegameNum, Common::String &description); +	int loadSavegame(int savegameNum); +	 +	void delayTicks(int a1); +	void delayTicksCursor(int a1); +	 +	void setHotspot(int index, int16 x1, int16 y1, int16 x2, int16 y2, uint16 flags = 0, +		int16 walkX = -1, int16 walkY = -1); +	int getHotspotIndexAtPos(int16 x, int16 y); +	void updateCursorByHotspot(); +	int getClickedHotspotId(); +	 +	int getInventoryItemSpriteNum(int index); +	 +	void updateMouseCursor(); +	void setVerbCursor(int verbCursor); +	void setCursor(int cursorIndex); +	void showCursor(); +	void hideCursor(); +	 +	void setGrabCursorSprite(int index); +	void createGrabCursorSprite(int spriteId); +	void freeGrabCursorSprite(); +	void updateGrabCursorSprite(int x, int y); +	 +	void invClear(); +	void invAdd(int itemId); +	void invRemove(int itemId); +	bool invHas(int itemId); +	 +	void clearFlags(); +	void setFlag(int num); +	void clearFlag(int num); +	bool isFlag(int num); +	 +	Graphics::Surface *addFullScreenSprite(int resourceId, int id); +	void removeFullScreenSprite(); +	void showFullScreenSprite(int resourceId); +	 +	void queueInsertDeviceIcon(); +	void insertDeviceIconActive(); +	void removeDeviceIconActive(); +	void setDeviceHotspot(int hotspotIndex, int x1, int y1, int x2, int y2); +	 +	int getSequenceTotalDuration(int resourceId); +	 +	bool isSoundPlaying(int resourceId); +	void playSound(int resourceId, bool looping); +	void stopSound(int resourceId); +	void setSoundVolume(int resourceId, int volume); + +	void updateTimers(); +	 +	void initGameFlags(int num); +	void loadStockDat(); + +	void mainLoop(); +	void initScene(); +	void endSceneInit(); +	void afterScene(); +	 +	int initSceneLogic(); +	void runSceneLogic(); +	 +	void checkGameKeys(); +	 +	void startSoundTimerA(int timerIndex); +	int playSoundA(); +	void startSoundTimerB(int timerIndex); +	int playSoundB(); +	void startSoundTimerC(int timerIndex); +	int playSoundC(); +	void startIdleTimer(int timerIndex); +	void updateIdleTimer(); +	 +	void screenEffect(int dir, byte r, byte g, byte b); +	 +	bool isKeyStatus1(int key); +	bool isKeyStatus2(int key); +	void clearKeyStatus1(int key); +	void clearAllKeyStatus1(); +	 +	void deleteSurface(Graphics::Surface **surface); +	 +	// Menu +	int _menuStatus; +	int _menuSpritesIndex; +	bool _menuDone; +	Graphics::Surface *_menuBackgroundSurface; +	Graphics::Surface *_menuQuitQuerySprite; +	Graphics::Surface *_largeSprite; +	Graphics::Surface *_menuSaveLoadSprite; +	Graphics::Surface *_menuSprite2; +	Graphics::Surface *_menuSprite1;	 +	char _savegameFilenames[7][30]; +	Graphics::Surface *_savegameSprites[7]; +	Graphics::Surface *_spriteHandle; +	Graphics::Surface *_cursorSprite; +	int _menuInventoryIndices[30]; +	Graphics::Surface *_menuInventorySprites[30]; +	int _savegameIndex; +	void createMenuSprite(); +	void freeMenuSprite(); +	void initMenuHotspots1(); +	void initMenuHotspots2(); +	void initMenuQuitQueryHotspots(); +	void initSaveLoadHotspots(); +	void drawInventoryFrames(); +	void insertInventorySprites(); +	void removeInventorySprites();	 +	void runMenu(); +	void updateMenuStatusInventory(); +	void updateMenuStatusMainMenu(); +	void updateMenuStatusSaveGame(); +	void updateMenuStatusLoadGame(); +	void updateMenuStatusQueryQuit(); +	 +	// Grid common +	int _gnapGridX, _gnapGridY; +	int _platGridX, _platGridY; +	int _gridMinX, _gridMinY; +	int _gridMaxX, _gridMaxY; +	bool isPointBlocked(int gridX, int gridY); +	void initSceneGrid(int gridMinX, int gridMinY, int gridMaxX, int gridMaxY); +	bool testWalk(int animationIndex, int someStatus, int gridX1, int gridY1, int gridX2, int gridY2); + +	// Gnap walking +	int _gnapWalkNodesCount; +	GridStruct _gnapWalkNodes[kMaxGridStructs]; +	int _gnapX, _gnapY; +	int _gnapWalkDestX, _gnapWalkDestY; +	int _gnapWalkDeltaX, _gnapWalkDeltaY, _gnapWalkDirX, _gnapWalkDirY, _gnapWalkDirXIncr, _gnapWalkDirYIncr; + +	int getGnapWalkSequenceId(int deltaX, int deltaY); +	int getGnapWalkStopSequenceId(int deltaX, int deltaY); +	int getGnapWalkFacing(int deltaX, int deltaY); +	bool gridSub41F08B(int gridX, int gridY); +	bool gridSub41F5FC(int gridX, int gridY, int index); +	bool gridSub41FAD5(int gridX, int gridY, int index); +	bool gnapFindPath3(int gridX, int gridY); +	bool gnapWalkTo(int gridX, int gridY, int animationIndex, int sequenceId, int flags); +	void gnapWalkStep(); +	 +	// Beaver walking +	int _platWalkNodesCount; +	GridStruct _platWalkNodes[kMaxGridStructs]; +	int _platX, _platY; +	int _platWalkDestX, _platWalkDestY; +	int _platWalkDeltaX, _platWalkDeltaY, _platWalkDirX, _platWalkDirY, _platWalkDirXIncr, _platWalkDirYIncr; +	 +	int getBeaverWalkSequenceId(int deltaX, int deltaY); +	bool gridSub423750(int gridX, int gridY); +	bool gridSub423CC1(int gridX, int gridY, int index); +	bool gridSub42419A(int gridX, int gridY, int index); +	bool platFindPath3(int gridX, int gridY); +	bool platypusWalkTo(int gridX, int gridY, int animationIndex, int sequenceId, int flags); +	void platypusWalkStep(); +	void beaverMakeRoom(); + +	// Gnap +	int _gnapIdleFacing; +	int _gnapActionStatus; +	int _gnapBrainPulseNum, _gnapBrainPulseRndValue; +	int _gnapSequenceId, _gnapSequenceDatNum, _gnapId; +	int _gnapRandomValue; + +	int getGnapSequenceId(int kind, int gridX, int gridY); +	int getGnapShowSequenceId(int index, int gridX, int gridY); +	void gnapIdle(); +	void gnapActionIdle(int sequenceId); +	void playGnapSequence(int sequenceId); +	void playGnapImpossible(int gridX, int gridY); +	void playGnapScratchingHead(int gridX, int gridY); +	void playGnapMoan1(int gridX, int gridY); +	void playGnapMoan2(int gridX, int gridY); +	void playGnapBrainPulsating(int gridX, int gridY); +	void playGnapPullOutDevice(int gridX, int gridY); +	void playGnapPullOutDeviceNonWorking(int gridX, int gridY); +	void playGnapUseDevice(int gridX, int gridY); +	void playGnapIdle(int gridX, int gridY); +	void playGnapShowItem(int itemIndex, int gridLookX, int gridLookY); +	void playGnapShowCurrItem(int gridX, int gridY, int gridLookX, int gridLookY); +	void updateGnapIdleSequence(); +	void updateGnapIdleSequence2(); +	void initGnapPos(int gridX, int gridY, int facing); +	void gnapInitBrainPulseRndValue(); +	void gnapUseDeviceOnBeaver(); +	void doCallback(int callback); +	bool gnapPlatypusAction(int gridX, int gridY, int platSequenceId, int callback); +	void gnapKissPlatypus(int callback); +	void gnapUseJointOnPlatypus(); +	void gnapUseDisguiseOnPlatypus(); +	 +	// Beaver +	int _beaverFacing; +	int _beaverActionStatus; +	int _beaverSequenceId, _beaverSequenceDatNum, _beaverId; +	int getBeaverSequenceId(int kind, int gridX, int gridY); +	void playBeaverSequence(int sequenceId); +	void updateBeaverIdleSequence(); +	void beaverSub426234(); +	void initBeaverPos(int gridX, int gridY, int facing); +	 +	// Scenes +	 +	int _toyUfoNextSequenceId, _toyUfoSequenceId; +	int _toyUfoId; +	int _toyUfoActionStatus; +	int _toyUfoX; +	int _toyUfoY; +	 +	void initGlobalSceneVars(); + +    bool sceneXX_sub_4466B1(); +	void sceneXX_playRandomSound(int timerIndex); +	void playSequences(int fullScreenSpriteId, int sequenceId1, int sequenceId2, int sequenceId3); +	 +	// Scene 0 +	int scene00_init(); +	 +	// Scene 1 +	int _s01_pigsIdCtr, _s01_smokeIdCtr; +	Graphics::Surface *_s01_spaceshipSurface; +	int scene01_init(); +	void scene01_updateHotspots(); +	void scene01_run(); +	void scene01_updateAnimations(); +	 +	// Scene 2 +	int _s02_truckGrillCtr; +	int _s02_nextChickenSequenceId, _s02_currChickenSequenceId; +	int _s02_gnapTruckSequenceId; +	int scene02_init(); +	void scene02_updateHotspots(); +	void scene02_run(); +	void scene02_updateAnimations(); +	 +	// Scene 3 +	bool _s03_platypusHypnotized;	 +	bool _s03_platypusScared; +	int _s03_nextPlatSequenceId; +	int _s03_nextFrogSequenceId, _s03_currFrogSequenceId; +	int scene03_init(); +	void scene03_updateHotspots(); +	void scene03_run(); +	void scene03_updateAnimations(); + +	// Scene 4 +	bool _s04_triedWindow; +	int _s04_dogIdCtr; +	int _s04_nextDogSequenceId, _s04_currDogSequenceId; +	int scene04_init(); +	void scene04_updateHotspots(); +	void scene04_run(); +	void scene04_updateAnimations(); + +	// Scene 5 +	int _s05_nextChickenSequenceId, _s05_currChickenSequenceId; +	int scene05_init(); +	void scene05_updateHotspots(); +	void scene05_run(); +	void scene05_updateAnimations(); + +	// Scene 6 +	bool _s06_horseTurnedBack; +	int _s06_nextPlatSequenceId; +	int _s06_nextHorseSequenceId, _s06_currHorseSequenceId; +	int scene06_init(); +	void scene06_updateHotspots(); +	void scene06_run(); +	void scene06_updateAnimations(); + +	// Scene 7 +	int scene07_init(); +	void scene07_updateHotspots(); +	void scene07_run(); +	void scene07_updateAnimations(); + +	// Scene 8 +	int _s08_nextDogSequenceId, _s08_currDogSequenceId; +	int _s08_nextManSequenceId, _s08_currManSequenceId; +	int scene08_init(); +	void scene08_updateHotspots(); +	void scene08_updateAnimationsCb(); +	void scene08_run(); +	void scene08_updateAnimations(); + +	// Scene 9 +	int scene09_init(); +	void scene09_updateHotspots(); +	void scene09_run(); +	void scene09_updateAnimations(); + +	// Scene 10 +	int _s10_nextCookSequenceId, _s10_currCookSequenceId; +	int scene10_init(); +	void scene10_updateHotspots(); +	void scene10_run(); +	void scene10_updateAnimations(); +	void scene10_updateAnimationsCb(); + +	// Scene 11 +	int _s11_billardBallCtr; +	int _s11_nextHookGuySequenceId, _s11_currHookGuySequenceId; +	int _s11_nextGoggleGuySequenceId, _s11_currGoggleGuySequenceId; +	int scene11_init(); +	void scene11_updateHotspots(); +	void scene11_run(); +	void scene11_updateAnimations(); + +	// Scene 12 +	int _s12_nextBeardGuySequenceId, _s12_currBeardGuySequenceId; +	int _s12_nextToothGuySequenceId, _s12_currToothGuySequenceId; +	int _s12_nextBarkeeperSequenceId, _s12_currBarkeeperSequenceId; +	int scene12_init(); +	void scene12_updateHotspots(); +	void scene12_run(); +	void scene12_updateAnimations(); + +	// Scene 13 +	int _s13_backToiletCtr; +	int scene13_init(); +	void scene13_updateHotspots(); +	void scene13_showScribble(); +	void scene13_run(); +	void scene13_updateAnimations(); + +	// Scene 14 +	int scene14_init(); +	void scene14_updateHotspots(); +	void scene14_run(); +	void scene14_updateAnimations(); + +	// Scene 15 +	int _s15_nextRecordSequenceId, _s15_currRecordSequenceId; +	int _s15_nextSlotSequenceId, _s15_currSlotSequenceId; +	int _s15_nextUpperButtonSequenceId, _s15_currUpperButtonSequenceId; +	int _s15_nextLowerButtonSequenceId, _s15_currLowerButtonSequenceId;	 +	int scene15_init(); +	void scene15_updateHotspots(); +	void scene15_run(); +	void scene15_updateAnimations(); + +	// Scene 16 +	void scene16_initCutscene(); + +	// Scene 17 +	bool _s17_canTryGetWrench; +	int _s17_wrenchCtr, _s17_platPhoneCtr, _s17_platTryGetWrenchCtr; +	int _s17_nextPhoneSequenceId, _s17_currPhoneSequenceId; +	int _s17_nextWrenchSequenceId, _s17_currWrenchSequenceId; +	int _s17_nextCarWindowSequenceId, _s17_currCarWindowSequenceId; +	int scene17_init(); +	void scene17_updateHotspots(); +	void scene17_update(); +	void scene17_platHangUpPhone(); +	void scene17_run(); +	void scene17_updateAnimations(); + +	// Scene 18 +	int _s18_garbageCanPos; +	int _s18_platPhoneCtr; +	int _s18_platPhoneIter; +	int _s18_nextPhoneSequenceId, _s18_currPhoneSequenceId; +	Graphics::Surface *_s18_cowboyHatSurface; +	int scene18_init(); +	void scene18_updateHotspots(); +	void scene18_gnapCarryGarbageCanTo(int a1, int arg4, int animationIndex, int argC, int a5); +	void scene18_putDownGarbageCan(int animationIndex); +	void scene18_platEndPhoning(int a1); +	void scene18_closeHydrantValve(); +	void scene18_waitForGnapAction(); +	void scene18_run(); +	void scene18_updateAnimations(); + +	// Scene 19 +	int _s19_currShopAssistantSequenceId, _s19_nextShopAssistantSequenceId; +	int _s19_toyGrabCtr; +	int _s19_shopAssistantCtr; +	Graphics::Surface *_s19_pictureSurface; +	int scene19_init(); +	void scene19_updateHotspots(); +	void scene19_run(); +	void scene19_updateAnimations(); + +	// Scene 20 +	int _s20_currStonerGuySequenceId, _s20_nextStonerGuySequenceId; +	int _s20_currGroceryStoreGuySequenceId, _s20_nextGroceryStoreGuySequenceId; +	int _s20_stonerGuyCtr; +	bool _s20_stonerGuyShowingJoint; +	int _s20_groceryStoreGuyCtr; +	int scene20_init(); +	void scene20_updateHotspots(); +	void scene20_updateAnimationsCb(); +	void scene20_stopSounds(); +	void scene20_run(); +	void scene20_updateAnimations(); + +	// Scene 21 +	int _s21_currOldLadySequenceId, _s21_nextOldLadySequenceId; +	int scene21_init(); +	void scene21_updateHotspots(); +	void scene21_run(); +	void scene21_updateAnimations(); + +	// Scene 22 +	int _s22_currCashierSequenceId, _s22_nextCashierSequenceId; +	bool _s22_caughtBefore; +	int _s22_cashierCtr; +	int scene22_init(); +	void scene22_updateHotspots(); +	void scene22_run(); +	void scene22_updateAnimations(); + +	// Scene 23 +	int _s23_currStoreClerkSequenceId, _s23_nextStoreClerkSequenceId; +	int scene23_init(); +	void scene23_updateHotspots(); +	void scene23_run(); +	void scene23_updateAnimations(); + +	// Scene 24 +	int _s24_currWomanSequenceId, _s24_nextWomanSequenceId; +	int _s24_boySequenceId; +	int _s24_girlSequenceId; +	int scene24_init(); +	void scene24_updateHotspots(); +	void scene24_run(); +	void scene24_updateAnimations(); + +	// Scene 25 +	int _s25_currTicketVendorSequenceId, _s25_nextTicketVendorSequenceId; +	int scene25_init(); +	void scene25_updateHotspots(); +	void scene25_playAnims(int index); +	void scene25_run(); +	void scene25_updateAnimations(); + +	// Scene 26 +	int _s26_currKidSequenceId, _s26_nextKidSequenceId; +	int scene26_init(); +	void scene26_updateHotspots(); +	void scene26_run(); +	void scene26_updateAnimations(); + +	// Scene 27 +	int _s27_nextJanitorSequenceId; +	int _s27_currJanitorSequenceId; +	int scene27_init(); +	void scene27_updateHotspots(); +	void scene27_run(); +	void scene27_updateAnimations(); +		 +	// Scene 28 +	int _s28_dword_47EA5C; +	int _s28_dword_47EA60; +	int _s28_dword_474938; +	int scene28_init(); +	void scene28_updateHotspots(); +	void scene28_run(); +	void scene28_updateAnimations(); +	 +	// Scene 29 +	int _s29_dword_47EA74; +	int _s29_dword_47EA78; +	int _s29_dword_47EA7C; +	int _s29_dword_47EA80; +	int scene29_init(); +	void scene29_updateHotspots(); +	void scene29_run(); +	void scene29_updateAnimations(); + +	// Scene 30 +	int _s30_dword_47EA88; +	int _s30_dword_47EA8C; +	int scene30_init(); +	void scene30_updateHotspots(); +	void scene30_run(); +	void scene30_updateAnimations(); +	 +	// Scene 31 +	int _s31_dword_47EAA8; +	int _s31_dword_47EAAC; +	int _s31_dword_47EAB0; +	bool _s31_beerGuyDistracted; +	int _s31_dword_474940; +	int _s31_dword_47EAB4; +	int scene31_init(); +	void scene31_updateHotspots(); +	void scene31_run(); +	void scene31_updateAnimations(); + +	// Scene 32 +	int _s32_dword_47EADC; +	int scene32_init(); +	void scene32_updateHotspots(); +	void scene32_run(); +	void scene32_updateAnimations(); +	 +	int _s33_dword_47EAE4; +	int _s33_dword_47EAE8; +	int _s33_dword_47EAEC; +	int scene33_init(); +	void scene33_updateHotspots(); +	void scene33_run(); +	void scene33_updateAnimations(); + +	// Scene 38 +	int scene38_init(); +	void scene38_updateHotspots(); +	void scene38_run(); +	void scene38_updateAnimations(); + +	// Scene 39 +	int _s39_dword_47EAF8; +	int _s39_dword_47EAFC; +	int scene39_init(); +	void scene39_updateHotspots(); +	void scene39_run(); +	void scene39_updateAnimations(); + +	// Scene 40 +	int scene40_init(); +	void scene40_updateHotspots(); +	void scene40_run(); +	void scene40_updateAnimations(); + +	// Scene 4x +	void toyUfoSetStatus(int a1); +	int toyUfoGetSequenceId(); +	bool toyUfoCheckTimer(); +	void toyUfoFlyTo(int destX, int destY, int a3, int a4, int a5, int a6, int animationIndex); + +	// Scene 41 +	int _s41_dword_47F2C0; +	int _s41_dword_47F2C4; +	int _s41_dword_47F2C8; +	int _s41_dword_47F2CC; +	int scene41_init(); +	void scene41_updateHotspots(); +	void scene41_run(); +	void scene41_updateAnimations(); + +	// Scene 42 +	int _s42_dword_47F2B8; +	int _s42_dword_47F2BC; +	int scene42_init(); +	void scene42_updateHotspots(); +	void scene42_run(); +	void scene42_updateAnimations(); + +	// Scene 43 +	int _s43_dword_47F2B0; +	int _s43_dword_47F2B4; +	int scene43_init(); +	void scene43_updateHotspots(); +	void scene43_run(); +	void scene43_updateAnimations(); + +	// Scene 44 +	int _s44_dword_47EB04; +	int _s44_dword_47EB08; +	int _s44_dword_47EB0C; +	int _s44_dword_47EB10; +	int scene44_init(); +	void scene44_updateHotspots(); +	void scene44_run(); +	void scene44_updateAnimations(); +	 +	// Scene 45 +	int _s45_dword_4749BC; +	int _s45_dword_4749C0; +	int scene45_init(); +	void scene45_updateHotspots(); +	void scene45_run(); +	void scene45_updateAnimations(); + +	// Scene 46 +	int _s46_dword_47EB18; +	int _s46_dword_47EB1C; +	int _s46_dword_47EB20; +	int _s46_dword_47EB24; +	int scene46_init(); +	void scene46_updateHotspots(); +	void scene46_run(); +	void scene46_updateAnimations(); +	 +	// Scene 47 +	void scene47_initCutscene1(); +	void scene47_initCutscene2(); +	void scene47_initCutscene3(); +	void scene47_initCutscene4(); +	void scene47_initCutscene5(); +	void scene47_initCutscene6(); +	void scene47_initCutscene7(); + +	// Scene 48 +	void scene48_initCutscene(); + +	// Scene 49 +	int _s49_scoreBarPos, _s49_scoreLevel, _s49_scoreBarFlash; +	int _s49_obstacleIndex; +	Scene49Obstacle _s49_obstacles[5]; +	int _s49_truckSequenceId, _s49_truckId, _s49_truckLaneNum; +	int scene49_init(); +	void scene49_updateHotspots(); +	void scene49_checkObstacles(); +	void scene49_updateObstacle(int i); +	void scene49_increaseScore(int amount); +	void scene49_decreaseScore(int amount); +	void scene49_refreshScoreBar(); +	void scene49_clearObstacle(int index); +	void scene49_run(); +	void scene49_updateAnimations(); + +	// Scene 50 +	bool _s50_fightDone; +	int _s50_timesPlayed, _s50_timesPlayedModifier; +	int _s50_attackCounter; +	int _s50_roundNum, _s50_timeRemaining; +	int _s50_leftTongueRoundsWon, _s50_rightTongueRoundsWon; +	int _s50_leftTongueEnergyBarPos, _s50_rightTongueEnergyBarPos; +	int _s50_leftTongueSequenceId, _s50_leftTongueId; +	int _s50_leftTongueNextSequenceId, _s50_leftTongueNextId, _s50_leftTongueNextIdCtr; +	int _s50_rightTongueSequenceId, _s50_rightTongueId; +	int _s50_rightTongueNextSequenceId, _s50_rightTongueNextId, _s50_rightTongueNextIdCtr; +	int _s50_leftTongueEnergy, _s50_rightTongueEnergy; +	int scene50_init(); +	void scene50_updateHotspots(); +	bool scene50_tongueWinsRound(int tongueNum); +	void scene50_playWinAnim(int tongueNum, bool fightOver); +	void scene50_delayTicks(); +	void scene50_initRound(); +	bool scene50_updateCountdown(); +	void scene50_drawCountdown(int value); +	void scene50_playTonguesIdle(); +	void scene50_playRoundAnim(int roundNum); +	bool scene50_updateEnergyBars(int newLeftBarPos, int newRightBarPos); +	void scene50_waitForAnim(int animationIndex); +	int scene50_checkInput(); +	int scene50_getRightTongueAction(); +	void scene50_updateAnimations(); +	int scene50_getRightTongueActionTicks(); +	int scene50_getLeftTongueNextId(); +	int scene50_getRightTongueNextId(); +	void scene50_playWinBadgeAnim(int tongueNum); +	void scene50_run(); +	 +	// Scene 51 +	int _s51_cashAmount; +	int _s51_digits[4]; +	int _s51_digitSequenceIds[4]; +	int _s51_guySequenceId, _s51_guyNextSequenceId; +	int _s51_itemsCaughtCtr; +	int _s51_dropSpeedTicks; +	int _s51_nextDropItemKind, _s51_itemInsertX, _s51_itemInsertDirection; +	int _s51_platypusSequenceId, _s51_platypusNextSequenceId, _s51_platypusJumpSequenceId; +	bool _s51_dropLoseCash; +	int _s51_itemsCtr,_s51_itemsCtr1, _s51_itemsCtr2; +	Scene51Item _s51_items[6]; + +	int scene51_init(); +	void scene51_updateHotspots(); +	void scene51_clearItem(Scene51Item *item); +	void scene51_dropNextItem(); +	void scene51_updateItemAnimations(); +	int scene51_checkCollision(int sequenceId); +	void scene51_updateItemAnimation(Scene51Item *item, int index); +	void scene51_removeCollidedItems(); +	int scene51_itemIsCaught(Scene51Item *item); +	bool scene51_isJumpingRight(int sequenceId); +	bool scene51_isJumpingLeft(int sequenceId); +	bool scene51_isJumping(int sequenceId); +	void scene51_waitForAnim(int animationIndex); +	int scene51_getPosRight(int sequenceId); +	int scene51_getPosLeft(int sequenceId); +	void scene51_playIntroAnim(); +	void scene51_updateGuyAnimation(); +	int scene51_incCashAmount(int sequenceId); +	void scene51_winMinigame(); +	void scene51_playCashAppearAnim(); +	void scene51_updateCash(int amount); +	void scene51_drawDigit(int digit, int position); +	void scene51_initCashDisplay(); +	void scene51_run(); +	 +	// Scene 52 +	int _s52_liveAlienRows; +	int _s52_gameScore; +	bool _s52_soundToggle; +	int _s52_arcadeScreenLeft; +	int _s52_arcadeScreenRight; +	int _s52_arcadeScreenBottom; +	int _s52_shipsLeft; +	int _s52_shieldSpriteIds[3]; +	int _s52_shieldPosX[3]; +	int _s52_shipPosX; +	int _s52_shipCannonFired, _s52_shipCannonPosX, _s52_shipCannonPosY; +	int _s52_shipCannonFiring; +	int _s52_shipCannonWidth, _s52_shipCannonHeight; +	int _s52_shipCannonTopY; +	int _s52_shipMidX, _s52_shipMidY; +	bool _s52_shipFlag; +	bool _s52_aliensInitialized; +	int _s52_alienSpeed, _s52_alienDirection; +	int _s52_alienWidth, _s52_alienHeight; +	int _s52_alienLeftX, _s52_alienTopY; +	int _s52_alienRowDownCtr; +	int _s52_alienRowKind[7]; +	int _s52_alienRowAnims[7]; +	int _s52_alienRowIds[7]; +	int _s52_alienRowXOfs[7]; +	int _s52_alienCannonFired[3]; +	int _s52_alienCannonPosX[3]; +	int _s52_alienCannonPosY[3]; +	int _s52_alienCannonSequenceIds[3]; +	int _s52_alienCannonIds[3]; +	bool _s52_alienWave, _s52_alienSingle; +	int _s52_alienCounter; +	bool _s52_bottomAlienFlag; +	int _s52_aliensCount; +	int _s52_items[8][5]; +	int _s52_nextUfoSequenceId, _s52_ufoSequenceId; +	int scene52_init(); +	void scene52_updateHotspots(); +	void scene52_update(); +	void scene52_initShipCannon(int bottomY); +	void scene52_initAlienCannons(); +	void scene52_fireShipCannon(int posX); +	void scene52_fireAlienCannon(); +	int scene52_getFreeShipCannon(); +	int scene52_getFreeAlienCannon(); +	void scene52_updateShipCannon(); +	void scene52_updateAlienCannons(); +	void scene52_initAliens(); +	void scene52_initAlienRowKind(int rowNum, int alienKind); +	void scene52_insertAlienRow(int rowNum); +	void scene52_insertAlienRowAliens(int rowNum); +	void scene52_updateAlienRow(int rowNum); +	void scene52_moveDownAlienRow(); +	int scene52_updateHitAlien(); +	int scene52_getHitAlienNum(int rowNum); +	int scene52_alienCannonHitShip(int cannonNum); +	int scene52_alienCannonHitShield(int cannonNum); +	int scene52_shipCannonHitShield(int cannonNum); +	int scene52_shipCannonHitAlien(); +	void scene52_shipExplode(); +	int scene52_checkAlienRow(int a1); +	void scene52_updateAlienRowXOfs(); +	void scene52_initAlienSize(); +	void scene52_playSound(); +	void scene52_updateAliens(); +	void scene52_updateAlien(int rowNum); +	void scene52_loseShip(); +	void scene52_initShields(); +	void scene52_initAnims(); +	void scene52_drawScore(int a1); +	void scene52_run(); +	 +	// Scene 53 +	int _s53_currHandSequenceId; +	bool _s53_isGnapPhoning; +	int _s53_callsMadeCtr; +	uint _s53_callsRndUsed; +	int scene53_init(); +	void scene53_updateHotspots(); +	int scene53_pressPhoneNumberButton(int phoneNumber, int buttonNum); +	int scene53_getRandomCallIndex(); +	void scene53_runRandomCall(); +	void scene53_runChitChatLine(); +	void scene53_run(); + +	// Scene 54 +	void scene54_initCutscene1(); +	void scene54_initCutscene2(); + +	// Scene 99 +	int _s99_itemsCount; +	int _s99_dword_47F2F0[16]; +	int _s99_dword_47F330[16]; +	int _s99_dword_47F370[50]; +	byte _s99_canSkip[16]; +	int cutscene_init(); +	void cutscene_run(); + +}; + +} // End of namespace Gnap + +#endif // GNAP_H diff --git a/engines/gnap/grid.cpp b/engines/gnap/grid.cpp new file mode 100644 index 0000000000..522c72c491 --- /dev/null +++ b/engines/gnap/grid.cpp @@ -0,0 +1,1392 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/datarchive.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +void GnapEngine::initSceneGrid(int gridMinX, int gridMinY, int gridMaxX, int gridMaxY) { +	_gridMinX = gridMinX; +	_gridMinY = gridMinY; +	_gridMaxX = gridMaxX; +	_gridMaxY = gridMaxY; +	_gnapGridX = 410 - gridMinX; +	_gnapGridY = 450 - gridMinY; +	_platGridX = 396 - gridMinX; +	_platGridY = 347 - gridMinY; +} + +int GnapEngine::getGnapWalkSequenceId(int deltaX, int deltaY) { +	static const int _gnapWalkSequenceIds[9] = { +		0x7B2, 0x000, 0x7B4, +		0x7AD, 0x000, 0x7AE, +		0x7B1, 0x000, 0x7B3 +	}; +	// CHECKME This is a little weird +	return _gnapWalkSequenceIds[3 * deltaX + 3 + 1 + deltaY]; +} + +int GnapEngine::getGnapWalkStopSequenceId(int deltaX, int deltaY) { +	static const int _gnapWalkStopSequenceIds[9] = { +		0x7BC, 0x7BA, 0x7BA, +		0x7BC, 0x000, 0x7BA, +		0x7BB, 0x7B9, 0x7B9 +	}; +	// CHECKME This is a little weird +	return _gnapWalkStopSequenceIds[3 * deltaX + 3 + 1 + deltaY]; +} + +int GnapEngine::getGnapWalkFacing(int deltaX, int deltaY) { +	static const int _gnapWalkFacings[9] = { +		5, 3, 3, +		5, 0, 3, +		7, 1, 1 +	}; +	// CHECKME This is a little weird +	return _gnapWalkFacings[3 * deltaX + 3 + 1 + deltaY]; +} + +bool GnapEngine::isPointBlocked(int gridX, int gridY) { + +	if (gridX < 0 || gridX >= _gridMaxX || gridY < 0 || gridY >= _gridMaxY) +		return true; + +	if ((gridX == _gnapX && gridY == _gnapY) || (gridX == _platX && gridY == _platY)) +		return true; +		 +	const int x = _gridMinX + 75 * gridX; +	const int y = _gridMinY + 48 * gridY; + +	for (int i = 0; i < _hotspotsCount; ++i) { +		if (x >= _hotspots[i].x1 && x <= _hotspots[i].x2 && +			y >= _hotspots[i].y1 && y <= _hotspots[i].y2 && +			!(_hotspots[i].flags & SF_WALKABLE)) +			return true; +	} + +	return false; + +} + +bool GnapEngine::gridSub41F08B(int gridX, int gridY) { +	bool result = false; +	 +	_gnapWalkNodesCount = 0; +	_gnapWalkDirXIncr = 0; +	_gnapWalkDirYIncr = 0; +	_gnapWalkDeltaX = ABS(_gnapWalkDestX - gridX); +	_gnapWalkDeltaY = ABS(_gnapWalkDestY - gridY); + +	if (_gnapWalkDeltaX) +		_gnapWalkDirX = (_gnapWalkDestX - gridX) / _gnapWalkDeltaX; +	else +		_gnapWalkDirX = 0; + +	if (_gnapWalkDeltaY) +		_gnapWalkDirY = (_gnapWalkDestY - gridY) / _gnapWalkDeltaY; +	else +		_gnapWalkDirY = 0; + +	while (_gnapWalkDirXIncr < _gnapWalkDeltaX && _gnapWalkDirYIncr < _gnapWalkDeltaY) { +		_gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; +		_gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; +		if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +			_gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; +			_gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; +			++_gnapWalkDirXIncr; +			++_gnapWalkDirYIncr; +		} else if (_gnapWalkDeltaY - _gnapWalkDirYIncr > _gnapWalkDeltaX - _gnapWalkDirXIncr) { +			if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +				_gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; +				_gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; +				++_gnapWalkDirYIncr; +			} else if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +				_gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; +				_gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; +				++_gnapWalkDirXIncr; +			} else { +				_gnapWalkDeltaX = _gnapWalkDirXIncr; +				_gnapWalkDeltaY = _gnapWalkDirYIncr; +				--_gnapWalkNodesCount; +			} +		} else { +			if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +				_gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; +				_gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; +				++_gnapWalkDirXIncr; +			} else if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +				_gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; +				_gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; +				++_gnapWalkDirYIncr; +			} else { +				_gnapWalkDeltaX = _gnapWalkDirXIncr; +				_gnapWalkDeltaY = _gnapWalkDirYIncr; +				--_gnapWalkNodesCount; +			} +		} +		++_gnapWalkNodesCount; +	} +	 +	while (_gnapWalkDirXIncr < _gnapWalkDeltaX) { +		_gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; +		_gnapWalkNodes[_gnapWalkNodesCount].gridY1 = _gnapWalkDestY; +		if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDestY)) { +			_gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; +			_gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; +			++_gnapWalkDirXIncr; +			++_gnapWalkNodesCount; +		} else { +			_gnapWalkDeltaX = _gnapWalkDirXIncr; +		} +	} + +	while (_gnapWalkDirYIncr < _gnapWalkDeltaY) { +		_gnapWalkNodes[_gnapWalkNodesCount].gridX1 = _gnapWalkDestX; +		_gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; +		if (!isPointBlocked(_gnapWalkDestX, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +			_gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; +			_gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; +			++_gnapWalkDirYIncr; +			++_gnapWalkNodesCount; +		} else { +			_gnapWalkDeltaY = _gnapWalkDirYIncr; +		} +	} + +	if (gridX + _gnapWalkDirX * _gnapWalkDirXIncr != _gnapWalkDestX || gridY + _gnapWalkDirY * _gnapWalkDirYIncr != _gnapWalkDestY) { +		_gnapWalkDestX = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; +		_gnapWalkDestY = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; +		result = false; +	} else { +		result = true; +	} + +	return result; +} + +bool GnapEngine::gridSub41F5FC(int gridX, int gridY, int index) { +	_gnapWalkNodesCount = index; +	_gnapWalkDirXIncr = 0; +	_gnapWalkDirYIncr = 0; +	_gnapWalkDeltaX = ABS(_gnapWalkDestX - gridX); +	_gnapWalkDeltaY = ABS(_gnapWalkDestY - gridY); + +	if (_gnapWalkDeltaX) +		_gnapWalkDirX = (_gnapWalkDestX - gridX) / _gnapWalkDeltaX; +	else +		_gnapWalkDirX = 0; + +	if (_gnapWalkDeltaY) +		_gnapWalkDirY = (_gnapWalkDestY - gridY) / _gnapWalkDeltaY; +	else +		_gnapWalkDirY = 0; + +	while (_gnapWalkDirXIncr < _gnapWalkDeltaX && _gnapWalkDirYIncr < _gnapWalkDeltaY) { +		_gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; +		_gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; +		if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +			_gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; +			_gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; +			++_gnapWalkDirXIncr; +			++_gnapWalkDirYIncr; +		} else if (_gnapWalkDeltaY - _gnapWalkDirYIncr > _gnapWalkDeltaX - _gnapWalkDirXIncr) { +			if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +				_gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; +				_gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; +				++_gnapWalkDirYIncr; +			} else if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +				_gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; +				_gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; +				++_gnapWalkDirXIncr; +			} else +				return false; +		} else { +			if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +				_gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; +				_gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; +				++_gnapWalkDirXIncr; +			} else if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +				_gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; +				_gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; +				++_gnapWalkDirYIncr; +			} else +				return false; +		} +		++_gnapWalkNodesCount; +	} + +	while (_gnapWalkDirXIncr < _gnapWalkDeltaX) { +		_gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; +		_gnapWalkNodes[_gnapWalkNodesCount].gridY1 = _gnapWalkDestY; +		if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDestY)) { +			_gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; +			_gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; +			++_gnapWalkDirXIncr; +			++_gnapWalkNodesCount; +		} else +			return false; +	} + +	while (_gnapWalkDirYIncr < _gnapWalkDeltaY) { +		_gnapWalkNodes[_gnapWalkNodesCount].gridX1 = _gnapWalkDestX; +		_gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; +		if (!isPointBlocked(_gnapWalkDestX, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +			_gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; +			_gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; +			++_gnapWalkDirYIncr; +			++_gnapWalkNodesCount; +		} else +			return false; +	} + +	return true; +} + +bool GnapEngine::gridSub41FAD5(int gridX, int gridY, int index) { +	_gnapWalkNodesCount = index; +	_gnapWalkDirXIncr = 0; +	_gnapWalkDirYIncr = 0; +	_gnapWalkDeltaX = ABS(_gnapWalkDestX - gridX); +	_gnapWalkDeltaY = ABS(_gnapWalkDestY - gridY); + +	if (_gnapWalkDeltaX) +		_gnapWalkDirX = (_gnapWalkDestX - gridX) / _gnapWalkDeltaX; +	else +		_gnapWalkDirX = 0; + +	if (_gnapWalkDeltaY) +		_gnapWalkDirY = (_gnapWalkDestY - gridY) / _gnapWalkDeltaY; +	else +		_gnapWalkDirY = 0; + +	while (_gnapWalkDeltaY < _gnapWalkDeltaX - _gnapWalkDirXIncr) { +		_gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; +		_gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY; +		if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, gridY)) { +			_gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; +			_gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; +			++_gnapWalkDirXIncr; +			++_gnapWalkNodesCount; +		} else +			return false; +	} + +	while (_gnapWalkDeltaX < _gnapWalkDeltaY - _gnapWalkDirYIncr) { +		_gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX; +		_gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; +		if (!isPointBlocked(gridX, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +			_gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; +			_gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; +			++_gnapWalkDirYIncr; +			++_gnapWalkNodesCount; +		} else +			return false; +	} + +	while (_gnapWalkDirXIncr < _gnapWalkDeltaX && _gnapWalkDirYIncr < _gnapWalkDeltaY) { +		_gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; +		_gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; +		if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +			_gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; +			_gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; +			++_gnapWalkDirXIncr; +			++_gnapWalkDirYIncr; +		} else if (_gnapWalkDeltaY - _gnapWalkDirYIncr > _gnapWalkDeltaX - _gnapWalkDirXIncr) { +			if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +				_gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; +				_gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; +				++_gnapWalkDirYIncr; +			} else if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +				_gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; +				_gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; +				++_gnapWalkDirXIncr; +			} else +				return false; +		} else { +			if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +				_gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; +				_gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; +				++_gnapWalkDirXIncr; +			} else if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +				_gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; +				_gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; +				++_gnapWalkDirYIncr; +			} else +				return false; +		} +		++_gnapWalkNodesCount; +	} + +	while (_gnapWalkDirXIncr < _gnapWalkDeltaX) { +		_gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; +		_gnapWalkNodes[_gnapWalkNodesCount].gridY1 = _gnapWalkDestY; +		if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDestY)) { +			_gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; +			_gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; +			++_gnapWalkDirXIncr; +			++_gnapWalkNodesCount; +		} else +			return false; +	} + +	while (_gnapWalkDirYIncr < _gnapWalkDeltaY) { +		_gnapWalkNodes[_gnapWalkNodesCount].gridX1 = _gnapWalkDestX; +		_gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; +		if (!isPointBlocked(_gnapWalkDestX, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { +			_gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; +			_gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; +			++_gnapWalkDirYIncr; +			++_gnapWalkNodesCount; +		} else +			return false; +	} + +	return true; +} + +bool GnapEngine::gnapFindPath3(int gridX, int gridY) { +	int gridIncr = 1; +	bool done = false; + +	while (!done && gridIncr < _gridMaxX) { +		if (!isPointBlocked(gridX + gridIncr, gridY) && gridSub41F5FC(gridX + gridIncr, gridY, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX + i; +				_gnapWalkNodes[i].gridY1 = gridY; +				_gnapWalkNodes[i].deltaX = 1; +				_gnapWalkNodes[i].deltaY = 0; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(gridX - gridIncr, gridY) && gridSub41F5FC(gridX - gridIncr, gridY, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX - i; +				_gnapWalkNodes[i].gridY1 = gridY; +				_gnapWalkNodes[i].deltaX = -1; +				_gnapWalkNodes[i].deltaY = 0; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(gridX, gridY + gridIncr) && gridSub41F5FC(gridX, gridY + gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX; +				_gnapWalkNodes[i].gridY1 = gridY + i; +				_gnapWalkNodes[i].deltaX = 0; +				_gnapWalkNodes[i].deltaY = 1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(gridX, gridY - gridIncr) && gridSub41F5FC(gridX, gridY - gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX; +				_gnapWalkNodes[i].gridY1 = gridY - i; +				_gnapWalkNodes[i].deltaX = 0; +				_gnapWalkNodes[i].deltaY = -1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(gridX + gridIncr, gridY + gridIncr) && gridSub41F5FC(gridX + gridIncr, gridY + gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX + i; +				_gnapWalkNodes[i].gridY1 = gridY + i; +				_gnapWalkNodes[i].deltaX = 1; +				_gnapWalkNodes[i].deltaY = 1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(gridX - gridIncr, gridY + gridIncr) && gridSub41F5FC(gridX - gridIncr, gridY + gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX - i; +				_gnapWalkNodes[i].gridY1 = gridY + i; +				_gnapWalkNodes[i].deltaX = -1; +				_gnapWalkNodes[i].deltaY = 1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(gridX + gridIncr, gridY - gridIncr) && gridSub41F5FC(gridX + gridIncr, gridY - gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX + i; +				_gnapWalkNodes[i].gridY1 = gridY - i; +				_gnapWalkNodes[i].deltaX = 1; +				_gnapWalkNodes[i].deltaY = -1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(gridX - gridIncr, gridY - gridIncr) && gridSub41F5FC(gridX - gridIncr, gridY - gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX - i; +				_gnapWalkNodes[i].gridY1 = gridY - i; +				_gnapWalkNodes[i].deltaX = -1; +				_gnapWalkNodes[i].deltaY = -1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(gridX + gridIncr, gridY) && gridSub41FAD5(gridX + gridIncr, gridY, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX + i; +				_gnapWalkNodes[i].gridY1 = gridY; +				_gnapWalkNodes[i].deltaX = 1; +				_gnapWalkNodes[i].deltaY = 0; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(gridX - gridIncr, gridY) && gridSub41FAD5(gridX - gridIncr, gridY, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX - i; +				_gnapWalkNodes[i].gridY1 = gridY; +				_gnapWalkNodes[i].deltaX = -1; +				_gnapWalkNodes[i].deltaY = 0; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(gridX, gridY + gridIncr) && gridSub41FAD5(gridX, gridY + gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX; +				_gnapWalkNodes[i].gridY1 = gridY + i; +				_gnapWalkNodes[i].deltaX = 0; +				_gnapWalkNodes[i].deltaY = 1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(gridX, gridY - gridIncr) && gridSub41FAD5(gridX, gridY - gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX; +				_gnapWalkNodes[i].gridY1 = gridY - i; +				_gnapWalkNodes[i].deltaX = 0; +				_gnapWalkNodes[i].deltaY = -1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(gridX + gridIncr, gridY + gridIncr) && gridSub41FAD5(gridX + gridIncr, gridY + gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX + i; +				_gnapWalkNodes[i].gridY1 = gridY + i; +				_gnapWalkNodes[i].deltaX = 1; +				_gnapWalkNodes[i].deltaY = 1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(gridX - gridIncr, gridY + gridIncr) && gridSub41FAD5(gridX - gridIncr, gridY + gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX - i; +				_gnapWalkNodes[i].gridY1 = gridY + i; +				_gnapWalkNodes[i].deltaX = -1; +				_gnapWalkNodes[i].deltaY = 1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(gridX + gridIncr, gridY - gridIncr) && gridSub41FAD5(gridX + gridIncr, gridY - gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX + i; +				_gnapWalkNodes[i].gridY1 = gridY - i; +				_gnapWalkNodes[i].deltaX = 1; +				_gnapWalkNodes[i].deltaY = -1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(gridX - gridIncr, gridY - gridIncr) && gridSub41FAD5(gridX - gridIncr, gridY - gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_gnapWalkNodes[i].gridX1 = gridX - i; +				_gnapWalkNodes[i].gridY1 = gridY - i; +				_gnapWalkNodes[i].deltaX = -1; +				_gnapWalkNodes[i].deltaY = -1; +			} +			done = true; +			break; +		} +		++gridIncr; +	} + +	return done; +} + +bool GnapEngine::gnapWalkTo(int gridX, int gridY, int animationIndex, int sequenceId, int flags) { + +	int datNum = flags & 3; +	bool done = false; + +	_timers[2] = 200; +	_timers[3] = 300; + +	if (gridX < 0) +		gridX = (_leftClickMouseX - _gridMinX + 37) / 75; + +	if (gridY < 0) +		gridY = (_leftClickMouseY - _gridMinY + 24) / 48; + +	_gnapWalkDestX = CLIP(gridX, 0, _gridMaxX - 1); +	_gnapWalkDestY = CLIP(gridY, 0, _gridMaxY - 1); +	 +	if (animationIndex >= 0 && _gnapWalkDestX == _platX && _gnapWalkDestY == _platY) +		beaverMakeRoom(); + +	if (gridSub41F5FC(_gnapX, _gnapY, 0)) +		done = true; + +	if (!done && gridSub41FAD5(_gnapX, _gnapY, 0)) +		done = true; +		 +	if (!done && gnapFindPath3(_gnapX, _gnapY)) +		done = true; + +	if (!done && gridSub41F08B(_gnapX, _gnapY)) +		done = true; + +	gnapIdle(); + +	int gnapSequenceId = _gnapSequenceId; +	int gnapId = _gnapId; +	int gnapSequenceDatNum = _gnapSequenceDatNum; + +	debug(0, "_gnapWalkNodesCount: %d", _gnapWalkNodesCount); + +	for (int index = 0; index < _gnapWalkNodesCount; ++index) { +		_gnapWalkNodes[index].id = index + 20 * _gnapWalkNodes[index].gridY1; +		if (_gnapWalkNodes[index].deltaX == 1 && _gnapWalkNodes[index].deltaY == 0) { +			if (index % 2) { +				_gameSys->insertSequence(makeRid(datNum, 0x7AB), _gnapWalkNodes[index].id, +					makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId, +					9, 0, 75 * _gnapWalkNodes[index].gridX1 - _gnapGridX, 48 * _gnapWalkNodes[index].gridY1 - _gnapGridY); +				_gnapWalkNodes[index].sequenceId = 0x7AB; +				gnapSequenceId = 0x7AB; +			} else { +				_gameSys->insertSequence(makeRid(datNum, 0x7AC), _gnapWalkNodes[index].id, +					makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId, +					9, 0, 75 * _gnapWalkNodes[index].gridX1 - _gnapGridX, 48 * _gnapWalkNodes[index].gridY1 - _gnapGridY); +				_gnapWalkNodes[index].sequenceId = 0x7AC; +				gnapSequenceId = 0x7AC; +			} +		} else if (_gnapWalkNodes[index].deltaX == -1 && _gnapWalkNodes[index].deltaY == 0) { +			if (index % 2) { +				_gameSys->insertSequence(makeRid(datNum, 0x7AF), _gnapWalkNodes[index].id, +					makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId, +					9, 0, 75 * _gnapWalkNodes[index].gridX1 - _gnapGridX, 48 * _gnapWalkNodes[index].gridY1 - _gnapGridY); +				_gnapWalkNodes[index].sequenceId = 0x7AF; +				gnapSequenceId = 0x7AF; +			} else { +				_gameSys->insertSequence(makeRid(datNum, 0x7B0), _gnapWalkNodes[index].id, +					makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId, +					9, 0, 75 * _gnapWalkNodes[index].gridX1 - _gnapGridX, 48 * _gnapWalkNodes[index].gridY1 - _gnapGridY); +				_gnapWalkNodes[index].sequenceId = 0x7B0; +				gnapSequenceId = 0x7B0; +			} +		} else { +			if (_gnapWalkNodes[index].deltaY == -1) +				_gnapWalkNodes[index].id -= 10; +			else +				_gnapWalkNodes[index].id += 10; +			int newSequenceId = getGnapWalkSequenceId(_gnapWalkNodes[index].deltaX, _gnapWalkNodes[index].deltaY); +			_gameSys->insertSequence(makeRid(datNum, newSequenceId), _gnapWalkNodes[index].id, +				makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId, +				9, 0, 75 * _gnapWalkNodes[index].gridX1 - _gnapGridX, 48 * _gnapWalkNodes[index].gridY1 - _gnapGridY); +			_gnapWalkNodes[index].sequenceId = newSequenceId; +			gnapSequenceId = newSequenceId; +		} +		gnapId = _gnapWalkNodes[index].id; +		gnapSequenceDatNum = datNum; +	} + +	if (flags & 8) { +		if (_gnapWalkNodesCount > 0) { +			_gnapSequenceId = gnapSequenceId; +			_gnapId = gnapId; +			_gnapIdleFacing = getGnapWalkFacing(_gnapWalkNodes[_gnapWalkNodesCount - 1].deltaX, _gnapWalkNodes[_gnapWalkNodesCount - 1].deltaY); +			_gnapSequenceDatNum = datNum; +			if (animationIndex >= 0) +				_gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, animationIndex); +		} else if (animationIndex >= 0) { +			_gameSys->setAnimation(0x107D3, 1, animationIndex); +			_gameSys->insertSequence(0x107D3, 1, 0, 0, 0, 0, 0, 0); +		} +	} else { +		if (sequenceId >= 0 && sequenceId != -1) { +			_gnapSequenceId = ridToEntryIndex(sequenceId); +			_gnapSequenceDatNum = ridToDatIndex(sequenceId); +			if (_gnapSequenceId == 0x7B9) { +				_gnapIdleFacing = 1; +			} else { +				switch (_gnapSequenceId) { +				case 0x7BA: +					_gnapIdleFacing = 3; +					break; +				case 0x7BB: +					_gnapIdleFacing = 7; +					break; +				case 0x7BC: +					_gnapIdleFacing = 5; +					break; +				} +			} +		} else { +			if (_gnapWalkNodesCount > 0) { +				_gnapSequenceId = getGnapWalkStopSequenceId(_gnapWalkNodes[_gnapWalkNodesCount - 1].deltaX, _gnapWalkNodes[_gnapWalkNodesCount - 1].deltaY); +				_gnapIdleFacing = getGnapWalkFacing(_gnapWalkNodes[_gnapWalkNodesCount - 1].deltaX, _gnapWalkNodes[_gnapWalkNodesCount - 1].deltaY); +			} else if (gridX >= 0 || gridY >= 0) { +				switch (_gnapIdleFacing) { +				case 1: +					_gnapSequenceId = 0x7B9; +					break; +				case 3: +					_gnapSequenceId = 0x7BA; +					break; +				case 7: +					_gnapSequenceId = 0x7BB; +					break; +				default: +					_gnapSequenceId = 0x7BC; +					break; +				} +			} else { +				int v10 = _leftClickMouseX - (_gridMinX + 75 * _gnapX); +				int v11 = _leftClickMouseY - (_gridMinY + 48 * _gnapY); +				if (_leftClickMouseX == _gridMinX + 75 * _gnapX) +					++v10; +				if (_leftClickMouseY == _gridMinY + 48 * _gnapY) +					v11 = 1; +				_gnapSequenceId = getGnapWalkStopSequenceId(v10 / abs(v10), v11 / abs(v11)); +				_gnapIdleFacing = getGnapWalkFacing(v10 / abs(v10), v11 / abs(v11)); +			} +			_gnapSequenceDatNum = datNum; +		} + +		if (animationIndex < 0) { +			_gnapId = 20 * _gnapWalkDestY + 1; +		} else { +			_gnapId = _gnapWalkNodesCount + animationIndex + 20 * _gnapWalkDestY; +			_gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapWalkNodesCount + animationIndex + 20 * _gnapWalkDestY, animationIndex); +		} + +		if (flags & 4) { +			_gameSys->insertSequence(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +				makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId, +				9, 0, 0, 0); +		} else { +			_gameSys->insertSequence(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +				makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId, +				9, 0, 75 * _gnapWalkDestX - _gnapGridX, 48 * _gnapWalkDestY - _gnapGridY); +		} + +	} + +	_gnapX = _gnapWalkDestX; +	_gnapY = _gnapWalkDestY; + +	return done; +} + +void GnapEngine::gnapWalkStep() { +	bool done = false; +	for (int i = 1; i < _gridMaxX && !done; ++i) { +		done = true; +		if (!isPointBlocked(_gnapX + i, _gnapY)) +			gnapWalkTo(_gnapX + i, _gnapY, -1, -1, 1); +		else if (!isPointBlocked(_gnapX - i, _gnapY)) +			gnapWalkTo(_gnapX - i, _gnapY, -1, -1, 1); +		else if (!isPointBlocked(_gnapX, _gnapY + 1)) +			gnapWalkTo(_gnapX, _gnapY + 1, -1, -1, 1); +		else if (!isPointBlocked(_gnapX, _gnapY - 1)) +			gnapWalkTo(_gnapX, _gnapY - 1, -1, -1, 1); +		else if (!isPointBlocked(_gnapX + 1, _gnapY + 1)) +			gnapWalkTo(_gnapX + 1, _gnapY + 1, -1, -1, 1); +		else if (!isPointBlocked(_gnapX - 1, _gnapY + 1)) +			gnapWalkTo(_gnapX - 1, _gnapY + 1, -1, -1, 1); +		else if (!isPointBlocked(_gnapX + 1, _gnapY - 1)) +			gnapWalkTo(_gnapX + 1, _gnapY - 1, -1, -1, 1); +		else if (!isPointBlocked(_gnapX - 1, _gnapY - 1)) +			gnapWalkTo(_gnapX - 1, _gnapY - 1, -1, -1, 1); +		else +			done = false; +	} +} + +//////////////////////////////////////////////////////////////////////////////// + +int GnapEngine::getBeaverWalkSequenceId(int deltaX, int deltaY) { +	static const int _beaverWalkSequenceIds[9] = { +		0x7C5, 0x000, 0x7C8, +		0x7C4, 0x000, 0x7C7, +		0x7C3, 0x000, 0x7C6 +	}; +	// CHECKME This is a little weird +	return _beaverWalkSequenceIds[3 * deltaX + 3 + 1 + deltaY]; +} + +bool GnapEngine::gridSub423750(int gridX, int gridY) { +	bool result = false; +	 +	_platWalkNodesCount = 0; +	_platWalkDirXIncr = 0; +	_platWalkDirYIncr = 0; +	_platWalkDeltaX = ABS(_platWalkDestX - gridX); +	_platWalkDeltaY = ABS(_platWalkDestY - gridY); + +	if (_platWalkDeltaX) +		_platWalkDirX = (_platWalkDestX - gridX) / _platWalkDeltaX; +	else +		_platWalkDirX = 0; + +	if (_platWalkDeltaY) +		_platWalkDirY = (_platWalkDestY - gridY) / _platWalkDeltaY; +	else +		_platWalkDirY = 0; + +	while (_platWalkDirXIncr < _platWalkDeltaX && _platWalkDirYIncr < _platWalkDeltaY) { +		_platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr; +		_platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr; +		if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { +			_platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; +			_platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; +			++_platWalkDirXIncr; +			++_platWalkDirYIncr; +		} else if (_platWalkDeltaY - _platWalkDirYIncr > _platWalkDeltaX - _platWalkDirXIncr) { +			if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { +				_platWalkNodes[_platWalkNodesCount].deltaX = 0; +				_platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; +				++_platWalkDirYIncr; +			} else if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) { +				_platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; +				_platWalkNodes[_platWalkNodesCount].deltaY = 0; +				++_platWalkDirXIncr; +			} else { +				_platWalkDeltaX = _platWalkDirXIncr; +				_platWalkDeltaY = _platWalkDirYIncr; +				--_platWalkNodesCount; +			} +		} else { +			if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) { +				_platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; +				_platWalkNodes[_platWalkNodesCount].deltaY = 0; +				++_platWalkDirXIncr; +			} else if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { +				_platWalkNodes[_platWalkNodesCount].deltaX = 0; +				_platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; +				++_platWalkDirYIncr; +			} else { +				_platWalkDeltaX = _platWalkDirXIncr; +				_platWalkDeltaY = _platWalkDirYIncr; +				--_platWalkNodesCount; +			} +		} +		++_platWalkNodesCount; +	} + +	while (_platWalkDirXIncr < _platWalkDeltaX) { +		_platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr; +		_platWalkNodes[_platWalkNodesCount].gridY1 = _platWalkDestY; +		if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDestY)) { +			_platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; +			_platWalkNodes[_platWalkNodesCount].deltaY = 0; +			++_platWalkDirXIncr; +			++_platWalkNodesCount; +		} else { +			_platWalkDeltaX = _platWalkDirXIncr; +		} +	} + +	while (_platWalkDirYIncr < _platWalkDeltaY) { +		_platWalkNodes[_platWalkNodesCount].gridX1 = _platWalkDestX; +		_platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr; +		if (!isPointBlocked(_platWalkDestX, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { +			_platWalkNodes[_platWalkNodesCount].deltaX = 0; +			_platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; +			++_platWalkDirYIncr; +			++_platWalkNodesCount; +		} else { +			_platWalkDeltaY = _platWalkDirYIncr; +		} +	} + +	if (gridX + _platWalkDirX * _platWalkDirXIncr != _platWalkDestX || gridY + _platWalkDirY * _platWalkDirYIncr != _platWalkDestY) { +		_platWalkDestX = gridX + _platWalkDirX * _platWalkDirXIncr; +		_platWalkDestY = gridY + _platWalkDirY * _platWalkDirYIncr; +		result = false; +	} else { +		result = true; +	} + +	return result; +} + +bool GnapEngine::gridSub423CC1(int gridX, int gridY, int index) { +	_platWalkNodesCount = index; +	_platWalkDirXIncr = 0; +	_platWalkDirYIncr = 0; +	_platWalkDeltaX = ABS(_platWalkDestX - gridX); +	_platWalkDeltaY = ABS(_platWalkDestY - gridY); + +	if (_platWalkDeltaX) +		_platWalkDirX = (_platWalkDestX - gridX) / _platWalkDeltaX; +	else +		_platWalkDirX = 0; + +	if (_platWalkDeltaY) +		_platWalkDirY = (_platWalkDestY - gridY) / _platWalkDeltaY; +	else +		_platWalkDirY = 0; + +	while (_platWalkDirXIncr < _platWalkDeltaX && _platWalkDirYIncr < _platWalkDeltaY) { +		_platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr; +		_platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr; +		if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { +			_platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; +			_platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; +			++_platWalkDirXIncr; +			++_platWalkDirYIncr; +		} else if (_platWalkDeltaY - _platWalkDirYIncr > _platWalkDeltaX - _platWalkDirXIncr) { +			if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { +				_platWalkNodes[_platWalkNodesCount].deltaX = 0; +				_platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; +				++_platWalkDirYIncr; +			} else if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) { +				_platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; +				_platWalkNodes[_platWalkNodesCount].deltaY = 0; +				++_platWalkDirXIncr; +			} else +				return false; +		} else { +			if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) { +				_platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; +				_platWalkNodes[_platWalkNodesCount].deltaY = 0; +				++_platWalkDirXIncr; +			} else if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { +				_platWalkNodes[_platWalkNodesCount].deltaX = 0; +				_platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; +				++_platWalkDirYIncr; +			} else +				return false; +		} +		++_platWalkNodesCount; +	} + +	while (_platWalkDirXIncr < _platWalkDeltaX) { +		_platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr; +		_platWalkNodes[_platWalkNodesCount].gridY1 = _platWalkDestY; +		if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDestY)) { +			_platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; +			_platWalkNodes[_platWalkNodesCount].deltaY = 0; +			++_platWalkDirXIncr; +			++_platWalkNodesCount; +		} else +			return false; +	} + +	while (_platWalkDirYIncr < _platWalkDeltaY) { +		_platWalkNodes[_platWalkNodesCount].gridX1 = _platWalkDestX; +		_platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr; +		if (!isPointBlocked(_platWalkDestX, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { +			_platWalkNodes[_platWalkNodesCount].deltaX = 0; +			_platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; +			++_platWalkDirYIncr; +			++_platWalkNodesCount; +		} else +			return false; +	} + +	return true; +} + +bool GnapEngine::gridSub42419A(int gridX, int gridY, int index) { +	_platWalkNodesCount = index; +	_platWalkDirXIncr = 0; +	_platWalkDirYIncr = 0; +	_platWalkDeltaX = ABS(_platWalkDestX - gridX); +	_platWalkDeltaY = ABS(_platWalkDestY - gridY); + +	if (_platWalkDeltaX) +		_platWalkDirX = (_platWalkDestX - gridX) / _platWalkDeltaX; +	else +		_platWalkDirX = 0; + +	if (_platWalkDeltaY) +		_platWalkDirY = (_platWalkDestY - gridY) / _platWalkDeltaY; +	else +		_platWalkDirY = 0; + +	while (_platWalkDeltaY < _platWalkDeltaX - _platWalkDirXIncr) { +		_platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr; +		_platWalkNodes[_platWalkNodesCount].gridY1 = gridY; +		if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, gridY)) { +			_platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; +			_platWalkNodes[_platWalkNodesCount].deltaY = 0; +			++_platWalkDirXIncr; +			++_platWalkNodesCount; +		} else +			return false; +	} + +	while (_platWalkDeltaX < _platWalkDeltaY - _platWalkDirYIncr) { +		_platWalkNodes[_platWalkNodesCount].gridX1 = gridX; +		_platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr; +		if (!isPointBlocked(gridX, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { +			_platWalkNodes[_platWalkNodesCount].deltaX = 0; +			_platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; +			++_platWalkDirYIncr; +			++_platWalkNodesCount; +		} else +			return false; +	} + +	while (_platWalkDirXIncr < _platWalkDeltaX && _platWalkDirYIncr < _platWalkDeltaY) { +		_platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr; +		_platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr; +		if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { +			_platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; +			_platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; +			++_platWalkDirXIncr; +			++_platWalkDirYIncr; +		} else if (_platWalkDeltaY - _platWalkDirYIncr > _platWalkDeltaX - _platWalkDirXIncr) { +			if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { +				_platWalkNodes[_platWalkNodesCount].deltaX = 0; +				_platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; +				++_platWalkDirYIncr; +			} else if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) { +				_platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; +				_platWalkNodes[_platWalkNodesCount].deltaY = 0; +				++_platWalkDirXIncr; +			} else +				return false; +		} else { +			if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) { +				_platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; +				_platWalkNodes[_platWalkNodesCount].deltaY = 0; +				++_platWalkDirXIncr; +			} else if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { +				_platWalkNodes[_platWalkNodesCount].deltaX = 0; +				_platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; +				++_platWalkDirYIncr; +			} else +				return false; +		} +		++_platWalkNodesCount; +	} + +	while (_platWalkDirXIncr < _platWalkDeltaX) { +		_platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr; +		_platWalkNodes[_platWalkNodesCount].gridY1 = _platWalkDestY; +		if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDestY)) { +			_platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; +			_platWalkNodes[_platWalkNodesCount].deltaY = 0; +			++_platWalkDirXIncr; +			++_platWalkNodesCount; +		} else +			return false; +	} + +	while (_platWalkDirYIncr < _platWalkDeltaY) { +		_platWalkNodes[_platWalkNodesCount].gridX1 = _platWalkDestX; +		_platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr; +		if (!isPointBlocked(_platWalkDestX, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { +			_platWalkNodes[_platWalkNodesCount].deltaX = 0; +			_platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; +			++_platWalkDirYIncr; +			++_platWalkNodesCount; +		} else +			return false; +	} + +	return true; +} + +bool GnapEngine::platFindPath3(int gridX, int gridY) { +	int gridIncr = 1; +	bool done = false; + +	while (!done && gridIncr < _gridMaxX) { +		if (!isPointBlocked(_platX + gridIncr, _platY) && gridSub423CC1(_platX + gridIncr, _platY, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX + i; +				_platWalkNodes[i].gridY1 = _platY; +				_platWalkNodes[i].deltaX = 1; +				_platWalkNodes[i].deltaY = 0; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(_platX - gridIncr, _platY) && gridSub423CC1(_platX - gridIncr, _platY, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX - i; +				_platWalkNodes[i].gridY1 = _platY; +				_platWalkNodes[i].deltaX = -1; +				_platWalkNodes[i].deltaY = 0; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(_platX, _platY + gridIncr) && gridSub423CC1(_platX, _platY + gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX; +				_platWalkNodes[i].gridY1 = _platY + i; +				_platWalkNodes[i].deltaX = 0; +				_platWalkNodes[i].deltaY = 1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(_platX, _platY - gridIncr) && gridSub423CC1(_platX, _platY - gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX; +				_platWalkNodes[i].gridY1 = _platY - i; +				_platWalkNodes[i].deltaX = 0; +				_platWalkNodes[i].deltaY = -1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(_platX + gridIncr, _platY + gridIncr) && gridSub423CC1(_platX + gridIncr, _platY + gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX + i; +				_platWalkNodes[i].gridY1 = _platY + i; +				_platWalkNodes[i].deltaX = 1; +				_platWalkNodes[i].deltaY = 1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(_platX - gridIncr, _platY + gridIncr) && gridSub423CC1(_platX - gridIncr, _platY + gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX - i; +				_platWalkNodes[i].gridY1 = _platY + i; +				_platWalkNodes[i].deltaX = -1; +				_platWalkNodes[i].deltaY = 1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(_platX + gridIncr, _platY - gridIncr) && gridSub423CC1(_platX + gridIncr, _platY - gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX + i; +				_platWalkNodes[i].gridY1 = _platY - i; +				_platWalkNodes[i].deltaX = 1; +				_platWalkNodes[i].deltaY = -1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(_platX - gridIncr, _platY - gridIncr) && gridSub423CC1(_platX - gridIncr, _platY - gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX - i; +				_platWalkNodes[i].gridY1 = _platY - i; +				_platWalkNodes[i].deltaX = -1; +				_platWalkNodes[i].deltaY = -1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(_platX + gridIncr, _platY) && gridSub42419A(_platX + gridIncr, _platY, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX + i; +				_platWalkNodes[i].gridY1 = _platY; +				_platWalkNodes[i].deltaX = 1; +				_platWalkNodes[i].deltaY = 0; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(_platX - gridIncr, _platY) && gridSub42419A(_platX - gridIncr, _platY, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX - i; +				_platWalkNodes[i].gridY1 = _platY; +				_platWalkNodes[i].deltaX = -1; +				_platWalkNodes[i].deltaY = 0; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(_platX, _platY + gridIncr) && gridSub42419A(_platX, _platY + gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX; +				_platWalkNodes[i].gridY1 = _platY + i; +				_platWalkNodes[i].deltaX = 0; +				_platWalkNodes[i].deltaY = 1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(_platX, _platY - gridIncr) && gridSub42419A(_platX, _platY - gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX; +				_platWalkNodes[i].gridY1 = _platY - i; +				_platWalkNodes[i].deltaX = 0; +				_platWalkNodes[i].deltaY = -1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(_platX + gridIncr, _platY + gridIncr) && gridSub42419A(_platX + gridIncr, _platY + gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX + i; +				_platWalkNodes[i].gridY1 = _platY + i; +				_platWalkNodes[i].deltaX = 1; +				_platWalkNodes[i].deltaY = 1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(_platX - gridIncr, _platY + gridIncr) && gridSub42419A(_platX - gridIncr, _platY + gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX - i; +				_platWalkNodes[i].gridY1 = _platY + i; +				_platWalkNodes[i].deltaX = -1; +				_platWalkNodes[i].deltaY = 1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(_platX + gridIncr, _platY - gridIncr) && gridSub42419A(_platX + gridIncr, _platY - gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX + i; +				_platWalkNodes[i].gridY1 = _platY - i; +				_platWalkNodes[i].deltaX = 1; +				_platWalkNodes[i].deltaY = -1; +			} +			done = true; +			break; +		} +		if (!isPointBlocked(_platX - gridIncr, _platY - gridIncr) && gridSub42419A(_platX - gridIncr, _platY - gridIncr, gridIncr)) { +			for (int i = 0; i < gridIncr; ++i) { +				_platWalkNodes[i].gridX1 = _platX - i; +				_platWalkNodes[i].gridY1 = _platY - i; +				_platWalkNodes[i].deltaX = -1; +				_platWalkNodes[i].deltaY = -1; +			} +			done = true; +			break; +		} +		++gridIncr; +	} + +	return done; +} + +bool GnapEngine::platypusWalkTo(int gridX, int gridY, int animationIndex, int sequenceId, int flags) { +	 +	int datNum = flags & 3; +	bool done = false; + +	_timers[1] = 60; + +	if (gridX < 0) +		gridX = (_leftClickMouseX - _gridMinX + 37) / 75; + +	if (gridY < 0) +		gridY = (_leftClickMouseY - _gridMinY + 24) / 48; + +	_platWalkDestX = CLIP(gridX, 0, _gridMaxX - 1); +	_platWalkDestY = CLIP(gridY, 0, _gridMaxY - 1); + +	if (animationIndex >= 0 && _platWalkDestX == _gnapX && _platWalkDestY == _gnapY) +		gnapWalkStep(); + +	if (gridSub423CC1(_platX, _platY, 0)) +		done = true; + +	if (!done && gridSub42419A(_platX, _platY, 0)) +		done = true; +		 +	if (!done && platFindPath3(_platX, _platY)) +		done = true; + +	if (!done) +		gridSub423750(_platX, _platY); + +	int platSequenceId = _beaverSequenceId; +	int platId = _beaverId; +	int platSequenceDatNum = _beaverSequenceDatNum; + +	for (int index = 0; index < _platWalkNodesCount; ++index) { +		_platWalkNodes[index].id = index + 20 * _platWalkNodes[index].gridY1; +		if (_platWalkNodes[index].deltaX == 1 && _platWalkNodes[index].deltaY == 0) { +			if (index % 2) { +				_gameSys->insertSequence(makeRid(datNum, 0x7CD), _platWalkNodes[index].id, +					makeRid(platSequenceDatNum, platSequenceId), platId, +					9, 0, 75 * _platWalkNodes[index].gridX1 - _platGridX, 48 * _platWalkNodes[index].gridY1 - _platGridY); +				_platWalkNodes[index].sequenceId = 0x7CD; +				platSequenceId = 0x7CD; +			} else { +				_gameSys->insertSequence(makeRid(datNum, 0x7CE), _platWalkNodes[index].id, +					makeRid(platSequenceDatNum, platSequenceId), platId, +					9, 0, 75 * _platWalkNodes[index].gridX1 - _platGridX, 48 * _platWalkNodes[index].gridY1 - _platGridY); +				_platWalkNodes[index].sequenceId = 0x7CE; +				platSequenceId = 0x7CE; +			} +		} else if (_platWalkNodes[index].deltaX == -1 && _platWalkNodes[index].deltaY == 0) { +			if (index % 2) { +				_gameSys->insertSequence(makeRid(datNum, 0x7CF), _platWalkNodes[index].id, +					makeRid(platSequenceDatNum, platSequenceId), platId, +					9, 0, 75 * _platWalkNodes[index].gridX1 - _platGridX, 48 * _platWalkNodes[index].gridY1 - _platGridY); +				_platWalkNodes[index].sequenceId = 0x7CF; +				platSequenceId = 0x7CF; +			} else { +				_gameSys->insertSequence(makeRid(datNum, 0x7D0), _platWalkNodes[index].id, +					makeRid(platSequenceDatNum, platSequenceId), platId, +					9, 0, 75 * _platWalkNodes[index].gridX1 - _platGridX, 48 * _platWalkNodes[index].gridY1 - _platGridY); +				_platWalkNodes[index].sequenceId = 0x7D0; +				platSequenceId = 0x7D0; +			} +		} else { +			if (_platWalkNodes[index].deltaY == -1) +				_platWalkNodes[index].id -= 10; +			else +				_platWalkNodes[index].id += 10; +			int newSequenceId = getBeaverWalkSequenceId(_platWalkNodes[index].deltaX, _platWalkNodes[index].deltaY); +			_gameSys->insertSequence(makeRid(datNum, newSequenceId), _platWalkNodes[index].id, +				makeRid(platSequenceDatNum, platSequenceId), platId, +				9, 0, 75 * _platWalkNodes[index].gridX1 - _platGridX, 48 * _platWalkNodes[index].gridY1 - _platGridY); +			_platWalkNodes[index].sequenceId = newSequenceId; +			platSequenceId = newSequenceId; +		} +		platId = _platWalkNodes[index].id; +		platSequenceDatNum = datNum; +	} + +	if (flags & 8) { +		if (_platWalkNodesCount > 0) { +			_beaverSequenceId = platSequenceId; +			_beaverId = platId; +			_beaverSequenceDatNum = datNum; +			// CHECKME Not sure if this is correct... +			if (_platWalkNodes[_platWalkNodesCount - 1].deltaX > 0) +				_beaverFacing = 0; +			else if (_platWalkNodes[_platWalkNodesCount - 1].deltaX < 0) +				_beaverFacing = 4; +			else if (_platWalkNodes[_platWalkNodesCount - 1].gridX1 % 2) +				_beaverFacing = 4; +			else +				_beaverFacing = 0; +			if (animationIndex >= 0) +				_gameSys->setAnimation(makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId, animationIndex); +		} else if (animationIndex >= 0) { +			_gameSys->setAnimation(0x107D3, 1, animationIndex); +			_gameSys->insertSequence(0x107D3, 1, 0, 0, 0, 0, 0, 0); +		} +	} else { +		if (sequenceId >= 0 && sequenceId != -1) { +			_beaverSequenceId = ridToEntryIndex(sequenceId); +			_beaverSequenceDatNum = ridToDatIndex(sequenceId); +			if (_beaverSequenceId == 0x7C2) { +				_beaverFacing = 0; +			} else if (_beaverSequenceId == 0x7D2) { +				_beaverFacing = 4; +			} +		} else { +			if (_platWalkNodesCount > 0) { +				if (_platWalkNodes[_platWalkNodesCount - 1].deltaX > 0) { +					_beaverSequenceId = 0x7C2; +					_beaverFacing = 0; +				} else if (_platWalkNodes[_platWalkNodesCount - 1].deltaX < 0) { +					_beaverSequenceId = 0x7D2; +					_beaverFacing = 4; +				} else if (_platWalkNodes[0].deltaX > 0) { +					_beaverSequenceId = 0x7C2; +					_beaverFacing = 0; +				} else if (_platWalkNodes[0].deltaX < 0) { +					_beaverSequenceId = 0x7D2; +					_beaverFacing = 4; +				} else { +					_beaverSequenceId = 0x7D2; +					_beaverFacing = 4; +				} +			} else if (_beaverFacing > 0) { +				_beaverSequenceId = 0x7D2; +			} else { +				_beaverSequenceId = 0x7C2; +			} +			_beaverSequenceDatNum = datNum; +		} + +		if (animationIndex < 0) { +			_beaverId = 20 * _platWalkDestY; +		} else { +			_beaverId = animationIndex + 20 * _platWalkDestY; +			_gameSys->setAnimation(makeRid(_beaverSequenceDatNum, _beaverSequenceId), animationIndex + 20 * _platWalkDestY, animationIndex); +		} + +		if (flags & 4) +			_gameSys->insertSequence(makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId, +				makeRid(platSequenceDatNum, platSequenceId), platId, +				9, 0, 0, 0); +		else +			_gameSys->insertSequence(makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId, +				makeRid(platSequenceDatNum, platSequenceId), platId, +				9, 0, 75 * _platWalkDestX - _platGridX, 48 * _platWalkDestY - _platGridY); +	} + +	_platX = _platWalkDestX; +	_platY = _platWalkDestY; +	 +	return done; +} + +void GnapEngine::platypusWalkStep() { +	bool done = false; +	for (int i = 1; !done && i < _gridMaxX; ++i) { +		done = true; +		if (!isPointBlocked(_platX + i, _platY)) +			platypusWalkTo(_platX + i, _platY, -1, -1, 1); +		else if (!isPointBlocked(_platX - i, _platY)) +			platypusWalkTo(_platX - i, _platY, -1, -1, 1); +		else if (!isPointBlocked(_platX, _platY + 1)) +			platypusWalkTo(_platX, _platY + 1, -1, -1, 1); +		else if (!isPointBlocked(_platX, _platY - 1)) +			platypusWalkTo(_platX, _platY - 1, -1, -1, 1); +		else if (!isPointBlocked(_platX + 1, _platY + 1)) +			platypusWalkTo(_platX + 1, _platY + 1, -1, -1, 1); +		else if (!isPointBlocked(_platX - 1, _platY + 1)) +			platypusWalkTo(_platX - 1, _platY + 1, -1, -1, 1); +		else if (!isPointBlocked(_platX + 1, _platY - 1)) +			platypusWalkTo(_platX + 1, _platY - 1, -1, -1, 1); +		else if (!isPointBlocked(_platX - 1, _platY - 1)) +			platypusWalkTo(_platX - 1, _platY - 1, -1, -1, 1); +		else +			done = false; +	} +} + +void GnapEngine::beaverMakeRoom() { +	int rndGridX, rndGridY; +	do { +		rndGridY = getRandom(_gridMaxY); +		rndGridX = getRandom(_gridMaxX); +	} while (ABS(rndGridX - _platX) > 4 || ABS(rndGridY - _platY) > 3 || +		isPointBlocked(rndGridX, rndGridY)); +	platypusWalkTo(rndGridX, rndGridY, -1, -1, 1); +} + +} // End of namespace Gnap diff --git a/engines/gnap/menu.cpp b/engines/gnap/menu.cpp new file mode 100644 index 0000000000..e6fc073c53 --- /dev/null +++ b/engines/gnap/menu.cpp @@ -0,0 +1,811 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/datarchive.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +void GnapEngine::createMenuSprite() { +	_menuBackgroundSurface = _gameSys->createSurface(0x10002); +} + +void GnapEngine::freeMenuSprite() { +	_gameSys->removeSpriteDrawItem(_menuBackgroundSurface, 260); +	delayTicksCursor(5); +	deleteSurface(&_menuBackgroundSurface); +} + +void GnapEngine::initMenuHotspots1() { +	 +	int v0, v2 = 0; + +	for (int i = 0; i < 3; ++i) { +		int v1 = 0; +		while (v1 < 3) { +			_hotspots[v2].x1 = 87 * v1 + 262; +			_hotspots[v2].y1 = 74 * i + 69; +			_hotspots[v2].x2 = _hotspots[v2].x1 + 79; +			_hotspots[v2].y2 = _hotspots[v2].y1 + 66; +			_hotspots[v2].flags = 0; +			_hotspots[v2].id = v2; +			++v1; +			++v2; +		} +	} + +	_hotspots[v2].x1 = 330; +	_hotspots[v2].y1 = 350; +	_hotspots[v2].x2 = 430; +	_hotspots[v2].y2 = 460; +	_hotspots[v2].flags = 2; +	_hotspots[v2].id = v2; + +	v0 = v2 + 1; +	_hotspots[v0].x1 = 180; +	_hotspots[v0].y1 = 15; +	_hotspots[v0].x2 = 620; +	_hotspots[v0].y2 = 580; +	_hotspots[v0].flags = 0; +	_hotspots[v0].id = v0; + +	++v0; +	_hotspots[v0].x1 = 0; +	_hotspots[v0].y1 = 0; +	_hotspots[v0].x2 = 799; +	_hotspots[v0].y2 = 599; +	_hotspots[v0].flags = 0; +	_hotspots[v0].id = v0; + +	_hotspotsCount = v0 + 1; +} + +void GnapEngine::initMenuHotspots2() { +	int i, v0; +	 +	for (i = 0; i < 4; ++i) { +		_hotspots[i].x1 = 312; +		_hotspots[i].y1 = 48 * i + 85; +		_hotspots[i].x2 = _hotspots[i].x1 + 153; +		_hotspots[i].y2 = _hotspots[i].y1 + 37; +		_hotspots[i].flags = SF_GRAB_CURSOR; +		_hotspots[i].id = i; +	} +	_hotspots[i].x1 = 500; +	_hotspots[i].y1 = 72; +	_hotspots[i].x2 = 527; +	_hotspots[i].y2 = 99; +	_hotspots[i].flags = SF_DISABLED; +	_hotspots[i].id = i; +	v0 = i + 1; +	_hotspots[v0].x1 = 330; +	_hotspots[v0].y1 = 350; +	_hotspots[v0].x2 = 430; +	_hotspots[v0].y2 = 460; +	_hotspots[v0].flags = SF_GRAB_CURSOR; +	_hotspots[v0].id = v0; +	++v0; +	_hotspots[v0].x1 = 180; +	_hotspots[v0].y1 = 15; +	_hotspots[v0].x2 = 620; +	_hotspots[v0].y2 = 580; +	_hotspots[v0].flags = 0; +	_hotspots[v0].id = v0; +	++v0; +	_hotspots[v0].x1 = 0; +	_hotspots[v0].y1 = 0; +	_hotspots[v0].x2 = 799; +	_hotspots[v0].y2 = 599; +	_hotspots[v0].flags = 0; +	_hotspots[v0].id = v0; +	_hotspotsCount = v0 + 1; +} + +void GnapEngine::initMenuQuitQueryHotspots() { +	_hotspots[0].x1 = 311; +	_hotspots[0].y1 = 197; +	_hotspots[0].x2 = 377; +	_hotspots[0].y2 = 237; +	_hotspots[0].flags = SF_GRAB_CURSOR; +	_hotspots[0].id = 0; +	_hotspots[1].x1 = 403; +	_hotspots[1].y1 = 197; +	_hotspots[1].x2 = 469; +	_hotspots[1].y2 = 237; +	_hotspots[1].flags = SF_GRAB_CURSOR; +	_hotspots[1].id = 1; +	_hotspots[2].x1 = 330; +	_hotspots[2].y1 = 350; +	_hotspots[2].x2 = 430; +	_hotspots[2].y2 = 460; +	_hotspots[2].flags = SF_GRAB_CURSOR; +	_hotspots[2].id = 2; +	_hotspots[3].x1 = 180; +	_hotspots[3].y1 = 15; +	_hotspots[3].x2 = 620; +	_hotspots[3].y2 = 580; +	_hotspots[3].flags = 0; +	_hotspots[3].id = 3; +	_hotspots[4].x1 = 0; +	_hotspots[4].y1 = 0; +	_hotspots[4].x2 = 799; +	_hotspots[4].y2 = 599; +	_hotspots[4].flags = 0; +	_hotspots[4].id = 4; +	_hotspotsCount = 5; +} + +void GnapEngine::initSaveLoadHotspots() { +	int i, v0; +	for (i = 0; i < 7; ++i ) { +		_hotspots[i].x1 = 288; +		_hotspots[i].y1 = 31 * i + 74; +		_hotspots[i].x2 = _hotspots[i].x1 + 91; +		_hotspots[i].y2 = _hotspots[i].y1 + 22; +		_hotspots[i].flags = SF_GRAB_CURSOR; +		_hotspots[i].id = i; +	} +	if (_menuStatus == 2) { +		_hotspots[i].x1 = 416; +		_hotspots[i].y1 = 160; +		_hotspots[i].x2 = 499; +		_hotspots[i].y2 = 188; +		_hotspots[i].flags = SF_GRAB_CURSOR; +		_hotspots[i].id = i; +		++i; +	} +	_hotspots[i].x1 = 416; +	_hotspots[i].y1 = 213; +	_hotspots[i].x2 = 499; +	_hotspots[i].y2 = 241; +	_hotspots[i].flags = SF_GRAB_CURSOR; +	_hotspots[i].id = i; +	v0 = i + 1; +	_hotspots[v0].x1 = 330; +	_hotspots[v0].y1 = 350; +	_hotspots[v0].x2 = 430; +	_hotspots[v0].y2 = 460; +	_hotspots[v0].flags = SF_GRAB_CURSOR; +	_hotspots[v0].id = v0; +	++v0; +	_hotspots[v0].x1 = 180; +	_hotspots[v0].y1 = 15; +	_hotspots[v0].x2 = 620; +	_hotspots[v0].y2 = 580; +	_hotspots[v0].flags = 0; +	_hotspots[v0].id = v0; +	++v0; +	_hotspots[v0].x1 = 0; +	_hotspots[v0].y1 = 0; +	_hotspots[v0].x2 = 799; +	_hotspots[v0].y2 = 599; +	_hotspots[v0].flags = 0; +	_hotspots[v0].id = v0; +	_hotspotsCount = v0 + 1; +} + +void GnapEngine::drawInventoryFrames() { +	for (int i = 0; i < 9; ++i) +		_gameSys->drawSpriteToSurface(_menuBackgroundSurface, _hotspots[i].x1 - 93, _hotspots[i].y1, 0x10001); +} + +void GnapEngine::insertInventorySprites() { +	 +	for (int i = 0; i < 9; ++i) { +		_menuInventoryIndices[i] = -1; +		_gameSys->removeSpriteDrawItem(_menuInventorySprites[_sceneClickedHotspot], 261); +		_menuInventorySprites[i] = 0; +	} + +	_menuSpritesIndex = 0; + +	for (int index = 0; index < 30 && _menuSpritesIndex < 9; ++index) { +		if (invHas(index)) { +			_gameSys->drawSpriteToSurface(_menuBackgroundSurface, +				_hotspots[_menuSpritesIndex].x1 - 93, _hotspots[_menuSpritesIndex].y1, 0x10000); +			_menuInventorySprites[_menuSpritesIndex] = _gameSys->createSurface(getInventoryItemSpriteNum(index) | 0x10000); +			if (index != _grabCursorSpriteIndex) { +				_menuInventoryIndices[_menuSpritesIndex] = index; +				_gameSys->insertSpriteDrawItem(_menuInventorySprites[_menuSpritesIndex], +					_hotspots[_menuSpritesIndex].x1 + ((79 - _menuInventorySprites[_menuSpritesIndex]->w) / 2), +					_hotspots[_menuSpritesIndex].y1 + ((66 - _menuInventorySprites[_menuSpritesIndex]->h) / 2), +					261); +			} +			_hotspots[_menuSpritesIndex].flags = SF_GRAB_CURSOR; +			++_menuSpritesIndex; +		} +	} + +} + +void GnapEngine::removeInventorySprites() { +	for (int i = 0; i < _menuSpritesIndex; ++i) +		if (_menuInventorySprites[i]) +			_gameSys->removeSpriteDrawItem(_menuInventorySprites[i], 261); +	delayTicksCursor(5); +	for (int j = 0; j < _menuSpritesIndex; ++j) { +		if (_menuInventorySprites[j]) { +			deleteSurface(&_menuInventorySprites[j]); +			_menuInventorySprites[j] = 0; +			_menuInventoryIndices[j] = -1; +		} +	} +	_menuSpritesIndex = 0; +} + +void GnapEngine::runMenu() { + +	int v43; + +	_spriteHandle = 0; +	_cursorSprite = 0; +	_menuSprite1 = 0; +	_menuSprite2 = 0; +	_menuSaveLoadSprite = 0; +	_menuQuitQuerySprite = 0; + +	_menuStatus = 0; +	_menuDone = false; + +	createMenuSprite();//??? CHECKME Crashes when done in loadStockDat() find out why + +	insertDeviceIconActive(); + +	for (int i = 0; i < 7; ++i) { +		_savegameFilenames[i][0] = 0; +		_savegameSprites[i] = 0; +	} + +	v43 = 0; + +	if (_menuStatus == 0) { +		invAdd(kItemMagazine); +		setGrabCursorSprite(-1); +		hideCursor(); +		initMenuHotspots1(); +		drawInventoryFrames(); +		insertInventorySprites(); +		_gameSys->insertSpriteDrawItem(_menuBackgroundSurface, 93, 0, 260); +		showCursor(); +		// SetCursorPos(400, 300); +		setVerbCursor(GRAB_CURSOR); +		// pollMessages(); +	} + +	_timers[2] = 10; + +	while (!isKeyStatus1(8) && !isKeyStatus1(28) && !_sceneDone && !_menuDone) { + +		updateCursorByHotspot(); + +		switch (_menuStatus) { +		case 0: +			updateMenuStatusInventory(); +			break; +		case 1: +			updateMenuStatusMainMenu(); +			break; +		case 2: +			updateMenuStatusSaveGame(); +			break; +		case 3: +			updateMenuStatusLoadGame(); +			break; +		case 4: +			updateMenuStatusQueryQuit(); +			break; +		} +		 +		gameUpdateTick(); + +	} + +	removeInventorySprites(); +	if (_spriteHandle) +		_gameSys->removeSpriteDrawItem(_spriteHandle, 261); +	if (_menuSprite1) +		_gameSys->removeSpriteDrawItem(_menuSprite1, 262); +	if (_menuSprite2) +		_gameSys->removeSpriteDrawItem(_menuSprite2, 262); +	for (int i = 0; i < 7; ++i) +		if (_savegameSprites[i]) +			_gameSys->removeSpriteDrawItem(_savegameSprites[i], 263); +	if (_cursorSprite) +		_gameSys->removeSpriteDrawItem(_cursorSprite, 264); +	if (_menuSaveLoadSprite) +		_gameSys->removeSpriteDrawItem(_menuSaveLoadSprite, 262); +	if (_menuQuitQuerySprite) +		_gameSys->removeSpriteDrawItem(_menuQuitQuerySprite, 262); +	if (_menuBackgroundSurface) +		_gameSys->removeSpriteDrawItem(_menuBackgroundSurface, 260); + +	delayTicksCursor(5); + +	deleteSurface(&_spriteHandle); +	deleteSurface(&_menuSprite1); +	deleteSurface(&_menuSprite2); +	for (int i = 0; i < 7; ++i) +		deleteSurface(&_savegameSprites[i]); +	deleteSurface(&_cursorSprite); +	deleteSurface(&_menuSaveLoadSprite); +	deleteSurface(&_menuQuitQuerySprite); + +	_sceneClickedHotspot = -1; + +	_timers[2] = getRandom(20) + 30; +	_timers[3] = getRandom(200) + 50; +	_timers[0] = getRandom(75) + 75; +	_timers[1] = getRandom(20) + 30; + +	clearAllKeyStatus1(); + +	_mouseClickState.left = false; + +	removeDeviceIconActive(); +	 +	freeMenuSprite();//??? CHECKME +} + +void GnapEngine::updateMenuStatusInventory() { + +	static const struct { +		int item1, item2, resultItem; +	} kCombineItems[] = { +		{kItemGrass, kItemMud, kItemDisguise}, +		{kItemDice, kItemQuarterWithHole, kItemDiceQuarterHole}, +		{kItemPill, kItemBucketWithBeer, kItemBucketWithPill} +	}; + +	updateGrabCursorSprite(0, 0); +	_hotspots[0].x1 = 262; +	_hotspots[0].y1 = 69; +	_hotspots[0].x2 = 341; +	_hotspots[0].y2 = 135; +	_sceneClickedHotspot = -1; +	if (_timers[2] == 0) +		_sceneClickedHotspot = getClickedHotspotId(); +	if (_sceneClickedHotspot == -1 || _sceneClickedHotspot >= _menuSpritesIndex) { +		if (_sceneClickedHotspot == _hotspotsCount - 3) { +			if (_grabCursorSpriteIndex == -1) { +				_timers[2] = 10; +				playSound(0x108F4, 0); +				_menuStatus = 1; +				Common::Rect dirtyRect(_hotspots[0].x1, _hotspots[0].y1, _hotspots[2].x2, _hotspots[_hotspotsCount - 4].y2); +				drawInventoryFrames(); +				initMenuHotspots2(); +				removeInventorySprites(); +				if (!_menuSprite1) +					_menuSprite1 = _gameSys->createSurface(0x104F8); +				_gameSys->insertSpriteDrawItem(_menuSprite1, 288, 79, 262); +				_gameSys->insertDirtyRect(dirtyRect); +			} else { +				playSound(0x108F5, 0); +			} +		} else if (_sceneClickedHotspot == _hotspotsCount - 1) { +			_timers[2] = 10; +			playSound(0x108F5, 0); +			_menuDone = true; +		} +	} else if (_sceneClickedHotspot != -1 && _menuInventoryIndices[_sceneClickedHotspot] != -1 && _grabCursorSpriteIndex == -1) { +		_gameSys->removeSpriteDrawItem(_menuInventorySprites[_sceneClickedHotspot], 261); +		setGrabCursorSprite(_menuInventoryIndices[_sceneClickedHotspot]); +		_menuInventoryIndices[_sceneClickedHotspot] = -1; +	} else if (_sceneClickedHotspot != -1 && _menuInventoryIndices[_sceneClickedHotspot] == -1 && _grabCursorSpriteIndex != -1) { +		_menuInventoryIndices[_sceneClickedHotspot] = _grabCursorSpriteIndex; +		_gameSys->insertSpriteDrawItem(_menuInventorySprites[_sceneClickedHotspot], +			_hotspots[_sceneClickedHotspot].x1 + ((79 - _menuInventorySprites[_sceneClickedHotspot]->w) / 2), +			_hotspots[_sceneClickedHotspot].y1 + (66 - _menuInventorySprites[_sceneClickedHotspot]->h) / 2, +			261); +		setGrabCursorSprite(-1); +	} else if (_sceneClickedHotspot != -1 && _menuInventoryIndices[_sceneClickedHotspot] != -1 && _grabCursorSpriteIndex != -1) { +		int combineIndex = -1; +		for (int i = 0; i < ARRAYSIZE(kCombineItems); ++i) { +			if ((_grabCursorSpriteIndex == kCombineItems[i].item1 && _menuInventoryIndices[_sceneClickedHotspot] == kCombineItems[i].item2) || +				(_grabCursorSpriteIndex == kCombineItems[i].item2 && _menuInventoryIndices[_sceneClickedHotspot] == kCombineItems[i].item1)) { +				combineIndex = i; +				break; +			} +		} +		if (combineIndex >= 0) { +			invRemove(kCombineItems[combineIndex].item1); +			invRemove(kCombineItems[combineIndex].item2); +			invAdd(kCombineItems[combineIndex].resultItem); +			playSound(0x108AE, 0); +			deleteSurface(&_spriteHandle); // CHECKME +			_spriteHandle = _gameSys->createSurface(0x10001); +			_gameSys->insertSpriteDrawItem(_spriteHandle, _hotspots[_menuSpritesIndex - 1].x1, _hotspots[_menuSpritesIndex - 1].y1, 261); +			setGrabCursorSprite(kCombineItems[combineIndex].resultItem); +			removeInventorySprites(); +			insertInventorySprites(); +			delayTicksCursor(5); +		} else { +			playSound(0x108F5, 0); +		} +	} +} + +void GnapEngine::updateMenuStatusMainMenu() { +	_hotspots[0].x1 = 312; +	_hotspots[0].y1 = 85; +	_hotspots[0].x2 = 465; +	_hotspots[0].y2 = 122; +	_sceneClickedHotspot = -1; +	if (!_timers[2]) +		_sceneClickedHotspot = getClickedHotspotId(); +		 +	if (_sceneClickedHotspot != 1 && _sceneClickedHotspot != 0) { +		if (_sceneClickedHotspot != 2 && _hotspotsCount - 1 != _sceneClickedHotspot) { +			if (_sceneClickedHotspot == 3) { +				_timers[2] = 10; +				playSound(0x108F4, 0); +				_gameSys->removeSpriteDrawItem(_menuSprite1, 262); +				initMenuQuitQueryHotspots(); +				_menuStatus = 4; +				if (!_menuQuitQuerySprite) +					_menuQuitQuerySprite = _gameSys->createSurface(0x104FC); +				_gameSys->insertSpriteDrawItem(_menuQuitQuerySprite, 254, 93, 262); +			} else if (_sceneClickedHotspot == 4) { +				playSound(0x108F4, 0); +				Common::Rect dirtyRect(0, 0, 799, 599); +				hideCursor(); +				_largeSprite = _gameSys->allocSurface(800, 600); + +				for (int i = 0; i < 3; ++i) { + +					_timers[2] = 10; + +					if (i == 0) { +						_gameSys->drawSpriteToSurface(_largeSprite, 0, 0, 0x1078D); +						_gameSys->insertSpriteDrawItem(_largeSprite, 0, 0, 300); +						/* TODO +						if (_midiFlag) { +							playMidi("pause.mid", 0); +						} +						*/ +					} else if (i == 1) { +						_gameSys->drawSpriteToSurface(_largeSprite, 0, 0, 0x1078E); +						_gameSys->insertDirtyRect(dirtyRect); +					} else if (i == 2) { +						_gameSys->drawSpriteToSurface(_largeSprite, 0, 0, 0x1078F); +						_gameSys->insertDirtyRect(dirtyRect); +					} + +					while (!_mouseClickState.left && !isKeyStatus1(28) && !isKeyStatus1(30) && !isKeyStatus1(29) && !_timers[2]) { +						gameUpdateTick(); +					} + +					playSound(0x108F5, 0); +					_mouseClickState.left = false; +					clearKeyStatus1(28); +					clearKeyStatus1(29); +					clearKeyStatus1(30); +				} +				 +				_gameSys->removeSpriteDrawItem(_largeSprite, 300); +				delayTicksCursor(5); +				deleteSurface(&_largeSprite); +				showCursor(); +			} else if (_hotspotsCount - 3 == _sceneClickedHotspot) { +				_timers[2] = 10; +				playSound(0x108F4, 0); +				initMenuHotspots1(); +				/* TODO +				if (_mouseX < 93 || _mouseX > 638 || _mouseY < 0 || _mouseY > 600) +					SetCursorPos(400, 300); +					*/ +				_menuStatus = 0; +				if (_menuSprite1) +					_gameSys->removeSpriteDrawItem(_menuSprite1, 262); +				insertInventorySprites(); +				Common::Rect dirtyRect(_hotspots[0].x1, _hotspots[0].y1, _hotspots[2].x2, _hotspots[_hotspotsCount - 4].y2); +				_gameSys->insertDirtyRect(dirtyRect); +			} +		} else { +			playSound(0x108F5, 0); +			_menuDone = true; +		} +	} else { +		_timers[2] = 10; +		playSound(0x108F4, 0); +		_gameSys->removeSpriteDrawItem(_menuSprite1, 262); +		if (_menuSaveLoadSprite) +			deleteSurface(&_menuSaveLoadSprite); +		if (_sceneClickedHotspot == 1) { +			_menuStatus = 2; +			initSaveLoadHotspots(); +			_menuSaveLoadSprite = _gameSys->createSurface(0x104FB); +		} else { +			_menuStatus = 3; +			initSaveLoadHotspots(); +			_menuSaveLoadSprite = _gameSys->createSurface(0x104FA); +		} +		_gameSys->insertSpriteDrawItem(_menuSaveLoadSprite, 403, 72, 262); +		if (!_menuSprite2) +			_menuSprite2 = _gameSys->createSurface(0x104F9); +		_gameSys->insertSpriteDrawItem(_menuSprite2, 277, 66, 262); +		for (int i = 0; i < 7; ++i) { +			Common::String savegameDescription; +			if (!_savegameSprites[i]) +				_savegameSprites[i] = _gameSys->allocSurface(111, 40); +			if (readSavegameDescription(i + 1, savegameDescription) == 0) +				strncpy(_savegameFilenames[i], savegameDescription.c_str(), 40); +			_gameSys->drawTextToSurface(_savegameSprites[i], 0, 0, 255, 0, 0, _savegameFilenames[i]); +			_gameSys->insertSpriteDrawItem(_savegameSprites[i], 288, _hotspots[i].y1, 263); +		} +		_savegameIndex = -1; +	} +} + +void GnapEngine::updateMenuStatusSaveGame() { +#if 0 // TODO +	_hotspots[0].x1 = 288; +	_hotspots[0].y1 = 74; +	_hotspots[0].x2 = 379; +	_hotspots[0].y2 = 96; +	_sceneClickedHotspot = -1; +	if (!_timers[2]) +	_sceneClickedHotspot = getClickedHotspotId(); +	if (_hotspotsCount - 3 == _sceneClickedHotspot) +	{ +	_timers[2] = 10; +	playSound(0x108F4, 0); +	_menuStatus = 1; +	writeSavegame(_savegameIndex + 1, (int)&_savegameFilenames[30 * _savegameIndex], 1); +	} +	else if (_hotspotsCount - 4 == _sceneClickedHotspot) +	{ +	_timers[2] = 10; +	playSound(0x108F5, 0); +	_menuStatus = 1; +	if (strcmp(&v43, &_savegameFilenames[30 * _savegameIndex]) && _savegameIndex != -1) +	{ +	strcpy((char *)&_savegameFilenames[30 * _savegameIndex], &v43); +	if (_savegameSprites[_savegameIndex] != -1) +	{ +	_gameSys->removeSpriteDrawItem(_savegameSprites[_savegameIndex], 263); +	delayTicksCursor(5); +	memFreeHandle(_savegameSprites[_savegameIndex]); +	} +	v16 = getSpriteWidthById(0x104F9); +	_savegameSprites[_savegameIndex] = allocSprite(v16, 40, 128, 0); +	} +	} +	else if (_hotspotsCount - 5 == _sceneClickedHotspot) +	{ +	_timers[2] = 10; +	playSound(0x108F4, 0); +	if ((signed int)_savegameIndex > -1) +	writeSavegame(_savegameIndex + 1, (int)&_savegameFilenames[30 * _savegameIndex], 1); +	_menuStatus = 1; +	} +	else if (_hotspotsCount - 1 == _sceneClickedHotspot) +	{ +	_menuDone = true; +	} +	else if (_sceneClickedHotspot != -1 && _hotspotsCount - 2 != _sceneClickedHotspot) +	{ +	_timers[2] = 10; +	playSound(0x108F4, 0); +	v17 = strcmp(&v43, &_savegameFilenames[30 * _savegameIndex]); +	if (!v17) +	LOBYTE(v17) = 0; +	if ((unsigned int8)v17 & (_savegameIndex < 0xFFFFFFFF)) +	{ +	strcpy((char *)&_savegameFilenames[30 * _savegameIndex], &v43); +	if (_savegameSprites[_savegameIndex] != -1) +	{ +	_gameSys->removeSpriteDrawItem(_savegameSprites[_savegameIndex], 263); +	delayTicksCursor(5); +	memFreeHandle(_savegameSprites[_savegameIndex]); +	} +	v18 = getSpriteWidthById(0x104F9); +	_savegameSprites[_savegameIndex] = allocSprite(v18, 40, 128, 0); +	drawTextToSurface(_savegameSprites[_savegameIndex], 0, 0, 255, 0, 0, &_savegameFilenames[30 * _savegameIndex]); +	insertSpriteDrawItem(_savegameSprites[_savegameIndex], 288, _hotspots[_savegameIndex].y1, 263); +	} +	_savegameIndex = _sceneClickedHotspot; +	v46 = strlen(&_savegameFilenames[30 * _sceneClickedHotspot]); +	strcpy(&v43, &_savegameFilenames[30 * _sceneClickedHotspot]); +	if (_cursorSprite == -1) +	{ +	v19 = getTextHeight("_"); +	v20 = getTextWidth("_"); +	_cursorSprite = allocSprite(v20, v19, 128, 0); +	drawTextToSurface(_cursorSprite, 0, 0, 255, 0, 0, "_"); +	} +	else +	{ +	_gameSys->removeSpriteDrawItem(_cursorSprite, 264); +	} +	v21 = _hotspots[_savegameIndex].x2; +	v22 = v21 - getTextWidth("_"); +	if (v22 > getTextWidth(&_savegameFilenames[30 * _savegameIndex]) + 288) +	{ +	v25 = getTextWidth(&_savegameFilenames[30 * _savegameIndex]) + 288; +	insertSpriteDrawItem(_cursorSprite, v25, _hotspots[_savegameIndex].y1, 264); +	} +	else +	{ +	v23 = _hotspots[_savegameIndex].x2; +	v24 = v23 - getTextWidth("_"); +	insertSpriteDrawItem(_cursorSprite, v24, _hotspots[_savegameIndex].y1, 264); +	} +	} +	if ((signed int)_savegameIndex > -1 && keybChar) +	{ +	if ((keybChar < 'A' || keybChar > 'Z') && (keybChar < '0' || keybChar > '9') && keybChar != ' ') +	{ +	if (keybChar == 8) +	{ +	if ((signed int)v46 > 0) +	--v46; +	*(&_savegameFilenames[30 * _savegameIndex] + v46) = 0; +	if (_savegameSprites[_savegameIndex] != -1) +	{ +	_gameSys->removeSpriteDrawItem(_savegameSprites[_savegameIndex], 263); +	memFreeHandle(_savegameSprites[_savegameIndex]); +	} +	v32 = getSpriteWidthById(0x104F9); +	_savegameSprites[_savegameIndex] = allocSprite(v32, 40, 128, 0); +	drawTextToSurface(_savegameSprites[_savegameIndex], 0, 0, 255, 0, 0, &_savegameFilenames[30 * _savegameIndex]); +	insertSpriteDrawItem(_savegameSprites[_savegameIndex], 288, _hotspots[_savegameIndex].y1, 263); +	_gameSys->removeSpriteDrawItem(_cursorSprite, 264); +	v33 = _hotspots[_savegameIndex].y1; +	v34 = getTextWidth(&_savegameFilenames[30 * _savegameIndex]); +	insertSpriteDrawItem(_cursorSprite, LOWORD(_hotspots[_savegameIndex].x1) + v34, v33, 264); +	} +	else if (keybChar == 13) +	{ +	_menuStatus = 1; +	writeSavegame(_savegameIndex + 1, (int)&_savegameFilenames[30 * _savegameIndex], 1); +	} +	} +	else +	{ +	*(&_savegameFilenames[30 * _savegameIndex] + v46) = keybChar; +	if ((signed int)v46 < 28) +	++v46; +	*(&_savegameFilenames[30 * _savegameIndex] + v46) = 0; +	if (getTextWidth(&_savegameFilenames[30 * _savegameIndex]) > 91) +	{ +	--v46; +	*(&_savegameFilenames[30 * _savegameIndex] + v46) = 0; +	} +	drawTextToSurface(_savegameSprites[_savegameIndex], 0, 0, 255, 0, 0, &_savegameFilenames[30 * _savegameIndex]); +	v26 = getTextWidth(&_savegameFilenames[30 * _savegameIndex]); +	rect.right = _hotspots[_savegameIndex].x1 + v26; +	v27 = rect.right; +	rect.left = v27 - 2 * getTextWidth("W"); +	rect.top = _hotspots[_savegameIndex].y1; +	rect.bottom = _hotspots[_savegameIndex].y2; +	insertDirtyRect(&rect); +	_gameSys->removeSpriteDrawItem(_cursorSprite, 264); +	v28 = _hotspots[_savegameIndex].x2; +	v29 = getTextWidth("_"); +	if (v28 - v29 > rect.right) +	{ +	insertSpriteDrawItem(_cursorSprite, SLOWORD(rect.right), SLOWORD(rect.top), 264); +	} +	else +	{ +	v30 = _hotspots[_savegameIndex].x2; +	v31 = v30 - getTextWidth("_"); +	insertSpriteDrawItem(_cursorSprite, v31, SLOWORD(rect.top), 264); +	} +	clearKeyStatus1(8); +	} +	} +	keybChar = 0; +	if (_menuStatus == 1 || _menuDone) +	{ +	_gameSys->removeSpriteDrawItem(_menuSprite2, 262); +	_gameSys->removeSpriteDrawItem(_menuSaveLoadSprite, 262); +	for (i = 0; i < 7; ++i) +	_gameSys->removeSpriteDrawItem(_savegameSprites[i], 263); +	_gameSys->removeSpriteDrawItem(_cursorSprite, 264); +	if (!_menuDone) +	{ +	initMenuHotspots2(); +	insertSpriteDrawItem(_menuSprite1, 288, 79, 262); +	} +	} +#endif +} + +void GnapEngine::updateMenuStatusLoadGame() { +	_hotspots[0].x1 = 288; +	_hotspots[0].y1 = 74; +	_hotspots[0].x2 = 379; +	_hotspots[0].y2 = 96; +	_sceneClickedHotspot = -1; +	if (!_timers[2]) +		_sceneClickedHotspot = getClickedHotspotId(); +	if (_sceneClickedHotspot != -1 && _hotspotsCount - 2 != _sceneClickedHotspot) { +		_timers[2] = 10; +		if (_hotspotsCount - 4 <= _sceneClickedHotspot) { +			playSound(0x108F5, 0); +			_gameSys->removeSpriteDrawItem(_menuSprite2, 262); +			_gameSys->removeSpriteDrawItem(_menuSaveLoadSprite, 262); +			for (int i = 0; i < 7; ++i) +				_gameSys->removeSpriteDrawItem(_savegameSprites[i], 263); +			if (_hotspotsCount - 1 == _sceneClickedHotspot) { +				_menuDone = true; +			} else { +				_menuStatus = 1; +				initMenuHotspots2(); +				_gameSys->insertSpriteDrawItem(_menuSprite1, 288, 79, 262); +			} +		} else if (loadSavegame(_sceneClickedHotspot + 1)) { +			playSound(0x108F5, 0); +		} else { +			playSound(0x108F4, 0); +			_sceneDone = true; +		} +	} +} + +void GnapEngine::updateMenuStatusQueryQuit() { + +	_hotspots[0].x1 = 311; +	_hotspots[0].y1 = 197; +	_hotspots[0].x2 = 377; +	_hotspots[0].y2 = 237; + +	_sceneClickedHotspot = -1; + +	if (!_timers[2]) +		_sceneClickedHotspot = getClickedHotspotId(); +		 +	/*	_sceneClickedHotspot +		0	Yes +		1	No +		2	Button +		3	Display +		4	Background +	*/ + +	if (_sceneClickedHotspot == 0) { +		// Quit the game +		playSound(0x108F5, 0); +		_gameSys->removeSpriteDrawItem(_menuQuitQuerySprite, 262); +		_sceneDone = true; +		_gameDone = true; +	} else if (_sceneClickedHotspot == 4) { +		// Exit the device +		playSound(0x108F4, 0); +		_gameSys->removeSpriteDrawItem(_menuQuitQuerySprite, 262); +		_menuDone = true; +	} else if (_sceneClickedHotspot != -1) { +		// Return to the main menu +		playSound(0x108F4, 0); +		_gameSys->removeSpriteDrawItem(_menuQuitQuerySprite, 262); +		_timers[2] = 10; +		_menuStatus = 1; +		initMenuHotspots2(); +		_gameSys->insertSpriteDrawItem(_menuSprite1, 288, 79, 262); +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/module.mk b/engines/gnap/module.mk new file mode 100644 index 0000000000..78e2cce736 --- /dev/null +++ b/engines/gnap/module.mk @@ -0,0 +1,70 @@ +MODULE := engines/gnap + +MODULE_OBJS := \ +	datarchive.o \ +	detection.o \ +	gamesys.o \ +	gnap.o \ +	grid.o \ +	menu.o \ +	resource.o \ +	sound.o \ +	scenes/scene01.o \ +	scenes/scene02.o \ +	scenes/scene03.o \ +	scenes/scene04.o \ +	scenes/scene05.o \ +	scenes/scene06.o \ +	scenes/scene07.o \ +	scenes/scene08.o \ +	scenes/scene09.o \ +	scenes/scene10.o \ +	scenes/scene11.o \ +	scenes/scene12.o \ +	scenes/scene13.o \ +	scenes/scene14.o \ +	scenes/scene15.o \ +	scenes/scene16.o \ +	scenes/scene17.o \ +	scenes/scene18.o \ +	scenes/scene19.o \ +	scenes/scene20.o \ +	scenes/scene21.o \ +	scenes/scene22.o \ +	scenes/scene23.o \ +	scenes/scene24.o \ +	scenes/scene25.o \ +	scenes/scene26.o \ +	scenes/scene27.o \ +	scenes/scene28.o \ +	scenes/scene29.o \ +	scenes/scene30.o \ +	scenes/scene31.o \ +	scenes/scene32.o \ +	scenes/scene33.o \ +	scenes/scene38.o \ +	scenes/scene39.o \ +	scenes/scene40.o \ +	scenes/scene41.o \ +	scenes/scene42.o \ +	scenes/scene43.o \ +	scenes/scene44.o \ +	scenes/scene45.o \ +	scenes/scene46.o \ +	scenes/scene47.o \ +	scenes/scene48.o \ +	scenes/scene49.o \ +	scenes/scene50.o \ +	scenes/scene51.o \ +	scenes/scene52.o \ +	scenes/scene53.o \ +	scenes/scene54.o \ +	scenes/scenecore.o + +# This module can be built as a plugin +ifeq ($(ENABLE_GNAP), DYNAMIC_PLUGIN) +PLUGIN := 1 +endif + +# Include common rules +include $(srcdir)/rules.mk diff --git a/engines/gnap/resource.cpp b/engines/gnap/resource.cpp new file mode 100644 index 0000000000..ab83b1376b --- /dev/null +++ b/engines/gnap/resource.cpp @@ -0,0 +1,118 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/resource.h" + +namespace Gnap { + +// SequenceFrame + +void SequenceFrame::loadFromStream(Common::MemoryReadStream &stream) { +	duration = stream.readUint16LE(); +	isScaled = stream.readUint16LE(); +	rect.left = stream.readUint32LE(); +	rect.top = stream.readUint32LE(); +	rect.right = stream.readUint32LE(); +	rect.bottom = stream.readUint32LE(); +	spriteId = stream.readUint32LE(); +	soundId = stream.readUint32LE(); +	unkValue = stream.readUint32LE(); +	//isScaled = 0;//DEBUG +	debug(1, "SequenceFrame() spriteId: %d; soundId: %d", spriteId, soundId); +} + +// SequenceAnimation + +void SequenceAnimation::loadFromStream(Common::MemoryReadStream &stream) { +	field_0 = stream.readUint16LE(); +	field_2 = stream.readUint16LE(); +	field_4 = stream.readUint32LE(); +	framesCount = stream.readUint16LE(); +	field_A = stream.readUint16LE(); +	debug(1, "SequenceAnimation() framesCount: %d", framesCount); +	frames = new SequenceFrame[framesCount]; +	for (int i = 0; i < framesCount; ++i) +		frames[i].loadFromStream(stream); +} + +// SequenceResource + +SequenceResource::SequenceResource(int resourceId, byte *data, uint32 size) { +	Common::MemoryReadStream stream(data, size, DisposeAfterUse::NO); +	_field_0 = stream.readUint32LE(); +	_sequenceId = stream.readUint32LE(); +	_field_8 = stream.readUint32LE(); +	_sequenceId2 = stream.readUint32LE(); +	_field_10 = stream.readUint32LE(); +	_flags = stream.readUint32LE(); +	_totalDuration = stream.readUint32LE(); +	_xOffs = stream.readUint16LE(); +	_yOffs = stream.readUint16LE(); +	_animationsCount = stream.readUint32LE(); +	_animations = new SequenceAnimation[_animationsCount]; +	debug(1, "SequenceResource() _animationsCount: %d", _animationsCount); +	for (int i = 0; i < _animationsCount; ++i) { +		uint32 animationOffs = stream.readUint32LE(); +		debug(1, "animationOffs: %08X", animationOffs); +		uint32 oldOffs = stream.pos(); +		stream.seek(animationOffs); +		_animations[i].loadFromStream(stream); +		stream.seek(oldOffs); +	} +	// TODO Convert resourceIds +} + +SequenceResource::~SequenceResource() { +	delete[] _animations; +} + +// SpriteResource + +SpriteResource::SpriteResource(int resourceId, byte *data, uint32 size) { +	_data = data; +	_width = READ_LE_UINT16(_data); +	_height = READ_LE_UINT16(_data + 2); +	_unk1 = READ_LE_UINT16(_data + 4); +	_unk2 = READ_LE_UINT16(_data + 6); +	_transparent = READ_LE_UINT16(_data + 8); +	_colorsCount = READ_LE_UINT16(_data + 10); +	_palette = (uint32*)(_data + 12); +	_pixels = _data + 12 + _colorsCount * 4; +	debug(1, "SpriteResource() width: %d; height: %d; colorsCount: %d", _width, _height, _colorsCount); +} + +SpriteResource::~SpriteResource() { +	delete[] _data; +} + +// SoundResource + +SoundResource::SoundResource(int resourceId, byte *data, uint32 size) { +	_data = data; +	_size = size; +} + +SoundResource::~SoundResource() { +	delete[] _data; +} + +} // End of namespace Gnap diff --git a/engines/gnap/resource.h b/engines/gnap/resource.h new file mode 100644 index 0000000000..b0f6a6169b --- /dev/null +++ b/engines/gnap/resource.h @@ -0,0 +1,196 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef GNAP_RESOURCE_H +#define GNAP_RESOURCE_H + +#include "common/array.h" +#include "common/events.h" +#include "common/file.h" +#include "common/memstream.h" +#include "common/str.h" +#include "common/stream.h" +#include "common/substream.h" +#include "common/system.h" + +#include "graphics/surface.h" + +#include "gnap/datarchive.h" + +namespace Gnap { + +enum { +	kResTypeSprite		= 0, +	kResTypeBitmap		= 1, +	kResTypeSound		= 2, +	kResTypeSequence	= 3 +}; + +struct SequenceFrame { +	int16 duration; +	int16 isScaled; +	Common::Rect rect; +	int32 spriteId; +	int32 soundId; +	int32 unkValue; +	void loadFromStream(Common::MemoryReadStream &stream); +}; + +struct SequenceAnimation { +	int16 field_0; +	int16 field_2; +	int32 field_4; +	int16 framesCount; +	int16 field_A; +	SequenceFrame *frames; +	SequenceAnimation() : frames(0) {} +	~SequenceAnimation() { delete[] frames; } +	void loadFromStream(Common::MemoryReadStream &stream); +}; + +class SequenceResource { +public: +	SequenceResource(int resourceId, byte *data, uint32 size); +	~SequenceResource(); +public: +	uint32 _field_0; +	int32 _sequenceId; +	int32 _field_8; +	int32 _sequenceId2; +	uint32 _field_10; +	uint32 _flags; +	int32 _totalDuration; +	int16 _xOffs; +	int16 _yOffs; +	int32 _animationsCount; +	SequenceAnimation *_animations; +}; + +class SpriteResource { +public: +	SpriteResource(int resourceId, byte *data, uint32 size); +	~SpriteResource(); +public: +	byte *_data; +	byte *_pixels; +	uint32 *_palette; +	int16 _width, _height; +	uint16 _unk1; +	uint16 _unk2; +	uint16 _transparent; +	uint16 _colorsCount; +}; + +class SoundResource { +public: +	SoundResource(int resourceId, byte *data, uint32 size); +	~SoundResource(); +public: +	byte *_data; +	uint32 _size; +}; + +template <class ResourceClass, int ResourceType, bool FreeAfterLoad> +class ResourceCacheTemplate { +public: + +	ResourceCacheTemplate(DatManager *dat) : _dat(dat) { +	} + +	~ResourceCacheTemplate() { +	} + +	ResourceClass *get(int resourceId) { +		Resource *resource = find(resourceId); +		if (!resource) { +			debug(1, "Loading resource type %d with ID %08X from disk", ResourceType, resourceId); +			resource = new Resource(load(resourceId)); +			_cache[resourceId] = resource; +		} else { +			debug(1, "Resource type %d with ID %08X was in cache", ResourceType, resourceId); +		} +		resource->_isLocked = true; +		return resource->_obj; +	} + +	void release(int resourceId) { +		Resource *resource = find(resourceId); +		if (resource) +			resource->_isLocked = false; +	} + +	void purge(bool force = false) { +		debug("Count before purge: %d", _cache.size()); +		for (CacheMapIterator it = _cache.begin(); it != _cache.end(); ++it) { +			Resource *resource = it->_value; +			if (force || !resource->_isLocked) { +				delete resource; +				_cache.erase(it); +			} +		} +		debug("Count after purge: %d", _cache.size()); +	} + +protected: + +	struct Resource { +		ResourceClass *_obj; +		bool _isLocked; +		Resource(ResourceClass *obj) : _obj(obj), _isLocked(false) {} +		~Resource() { delete _obj; } +	}; +	 +	typedef Common::HashMap<int, Resource*> CacheMap; +	typedef typename CacheMap::iterator CacheMapIterator; +	 +	DatManager *_dat; +	CacheMap _cache; + +	Resource *find(int resourceId) { +		CacheMapIterator it = _cache.find(resourceId); +		if (it != _cache.end()) +			return it->_value; +		return 0; +	} +	 +	ResourceClass *load(int resourceId) { +		if (_dat->getResourceType(resourceId) != ResourceType) { +			error("ResourceCache::load() Wrong resource type: Expected %d, got %d", ResourceType, _dat->getResourceType(resourceId)); +			return 0; +		} +		byte *resourceData = _dat->loadResource(resourceId); +		uint32 resourceSize = _dat->getResourceSize(resourceId); +		ResourceClass *obj = new ResourceClass(resourceId, resourceData, resourceSize); +		if (FreeAfterLoad) +			delete[] resourceData; +		return obj; +	} + +}; + +typedef ResourceCacheTemplate<SpriteResource, kResTypeSprite, false> SpriteCache; +typedef ResourceCacheTemplate<SoundResource, kResTypeSound, false> SoundCache; +typedef ResourceCacheTemplate<SequenceResource, kResTypeSequence, true> SequenceCache; + +} // End of namespace Gnap + +#endif // GNAP_RESOURCE_H diff --git a/engines/gnap/scenes/scene01.cpp b/engines/gnap/scenes/scene01.cpp new file mode 100644 index 0000000000..0e4695c619 --- /dev/null +++ b/engines/gnap/scenes/scene01.cpp @@ -0,0 +1,373 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSExitTruck	= 1, +	kHSMud			= 2, +	kHSPigs			= 3, +	kHSSpaceship	= 4, +	kHSDevice		= 5, +	kHSWalkArea1	= 6, +	kHSWalkArea2	= 7, +	kHSWalkArea3	= 8, +	kHSWalkArea4	= 9, +	kHSWalkArea5	= 10, +	kHSWalkArea6	= 11, +	kHSWalkArea7	= 12, +	kHSWalkArea8	= 13 +}; + +enum { +	kASLookSpaceship		= 1, +	kASLookSpaceshipDone	= 2, +	kASLeaveScene			= 3, +	kASTakeMud				= 5, +	kASLookPigs				= 6, +	kASUsePigs				= 7 +}; + +int GnapEngine::scene01_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 3); +	return 0x88; +} + +void GnapEngine::scene01_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED | SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitTruck, 780, 226, 800, 455, SF_EXIT_R_CURSOR | SF_WALKABLE, 10, 6); +	setHotspot(kHSMud, 138, 282, 204, 318, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 5); +	setHotspot(kHSPigs, 408, 234, 578, 326, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 4); +	setHotspot(kHSSpaceship, 0, 200, 94, 292, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 1, 6); +	setHotspot(kHSWalkArea1, 0, 0, 162, 426); +	setHotspot(kHSWalkArea2, 162, 0, 237, 396); +	setHotspot(kHSWalkArea3, 237, 0, 319, 363); +	setHotspot(kHSWalkArea4, 520, 0, 800, 404); +	setHotspot(kHSWalkArea5, 300, 447, 800, 600); +	setHotspot(kHSWalkArea6, 678, 0, 800, 404); +	setHotspot(kHSWalkArea7, 0, 0, 520, 351); +	setHotspot(kHSWalkArea8, 0, 546, 300, 600); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +    if (isFlag(0)) +		_hotspots[kHSPlatypus].flags = SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR; +    if (isFlag(1)) +		_hotspots[kHSMud].flags = SF_WALKABLE | SF_DISABLED; +	_hotspotsCount = 14; +} + +void GnapEngine::scene01_run() { + +	// NOTE Removed _s01_dword_474380 which was set when the mud was taken +	// which is also set in the global game flags. +	 +	playSound(0x1091C, 1); +	startSoundTimerC(5); + +	_gameSys->setAnimation(134, 20, 4); +	_gameSys->insertSequence(134, 20, 0, 0, kSeqNone, 0, 0, 0); + +	_gameSys->setAnimation(0x7F, 40, 2); +	_gameSys->insertSequence(0x7F, 40, 0, 0, kSeqNone, 0, 0, 0); + +	_timers[4] = getRandom(100) + 300; + +	if (!isFlag(1)) +		_gameSys->insertSequence(129, 40, 0, 0, kSeqNone, 0, 0, 0); + +	queueInsertDeviceIcon(); + +	if (_prevSceneNum == 2) { +		initGnapPos(11, 6, 3); +		if (isFlag(0)) +			initBeaverPos(12, 6, 4); +		endSceneInit(); +		if (isFlag(0)) +			platypusWalkTo(9, 6, -1, 0x107C2, 1); +		gnapWalkTo(8, 6, -1, 0x107B9, 1); +	} else { +		initGnapPos(1, 6, 1); +		if (isFlag(0)) +			initBeaverPos(1, 7, 0); +		endSceneInit(); +	} + +	while (!_sceneDone) { + +		updateMouseCursor(); +		updateCursorByHotspot(); +		testWalk(0, 3, -1, -1, -1, -1); + +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); + +		switch (_sceneClickedHotspot) { +		 +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene01_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0 && isFlag(0)) { +				if (_grabCursorSpriteIndex == kItemDisguise) { +					gnapUseDisguiseOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						if (isFlag(5)) +							playGnapMoan1(_platX, _platY); +						else +							playGnapScratchingHead(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSSpaceship: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, 2); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						_gnapIdleFacing = 5; +						if (gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1)) +							_gnapActionStatus = kASLookSpaceship; +						break; +					case GRAB_CURSOR: +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSMud: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 2, 3); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(3, 3); +						break; +					case GRAB_CURSOR: +						gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, getGnapSequenceId(gskIdle, 2, 3) | 0x10000, 1); +						_gnapActionStatus = kASTakeMud; +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSPigs: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 7, 2); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, 7, 2) | 0x10000, 1); +						_gnapActionStatus = kASLookPigs; +						break; +					case GRAB_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, 7, 2) | 0x10000, 1); +						_gnapActionStatus = kASUsePigs; +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskBrainPulsating, 7, 2) | 0x10000, 1); +						_gnapActionStatus = kASLookPigs; +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSExitTruck: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				gnapWalkTo(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y, 0, 0x107AB, 1); +				_gnapActionStatus = kASLeaveScene; +				if (isFlag(0)) +					platypusWalkTo(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y + 1, -1, 0x107CD, 1); +				_newSceneNum = 2; +			} +			break; + +		case kHSWalkArea1: +		case kHSWalkArea2: +		case kHSWalkArea3: +		case kHSWalkArea4: +		case kHSWalkArea5: +		case kHSWalkArea6: +		case kHSWalkArea7: +		case kHSWalkArea8: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; + +		default: +			if (_mouseClickState.left && _gnapActionStatus < 0) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; + +		} + +		scene01_updateAnimations(); + +		if (!isSoundPlaying(0x1091C)) +			playSound(0x1091C, 1); + +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0 && isFlag(0)) +				updateBeaverIdleSequence(); +			if (_gnapActionStatus < 0) +				updateGnapIdleSequence(); +			if (_timers[4] == 0) { +				// Update bird animation +				_timers[4] = getRandom(100) + 300; +				if (getRandom(1) == 0) +					_gameSys->insertSequence(0x84, 180, 0, 0, kSeqNone, 0, 0, 0); +				else +					_gameSys->insertSequence(0x83, 180, 0, 0, kSeqNone, 0, 0, 0); +			} +			playSoundC(); +		} + +		checkGameKeys(); +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene01_updateHotspots(); +		} +		 +		gameUpdateTick(); + +	} + +} + +void GnapEngine::scene01_updateAnimations() { +	 +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASLookSpaceship: +			_s01_spaceshipSurface = _gameSys->createSurface(47); +			_gameSys->insertSpriteDrawItem(_s01_spaceshipSurface, 0, 0, 255); +			_gameSys->setAnimation(133, 256, 0); +			_gameSys->insertSequence(133, 256, 0, 0, kSeqNone, 0, 0, 0); +			_gnapActionStatus = kASLookSpaceshipDone; +			break; +		case kASLookSpaceshipDone: +			_gameSys->removeSequence(133, 256, 1); +			_gameSys->removeSpriteDrawItem(_s01_spaceshipSurface, 255); +			deleteSurface(&_s01_spaceshipSurface); +			_gnapActionStatus = -1; +			break; +		case kASLeaveScene: +			_sceneDone = true; +			break; +		case kASTakeMud: +			playGnapPullOutDevice(2, 3); +			playGnapUseDevice(0, 0); +			_gameSys->insertSequence(128, 40, 129, 40, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(128, 40, 3); +			_gnapActionStatus = -1; +			break; +		case kASLookPigs: +			playSound(138, 0); +			playSound(139, 0); +			playSound(140, 0); +			_gnapActionStatus = -1; +			break; +		case kASUsePigs: +			playGnapPullOutDevice(7, 2); +			playGnapUseDevice(0, 0); +			_gameSys->insertSequence(135, 39, 0, 0, kSeqNone, 25, getRandom(140) - 40, 0); +			_gnapActionStatus = -1; +			break; +		} +	} + +	if (_gameSys->getAnimationStatus(3) == 2) { +		_gameSys->setAnimation(0, 0, 3); +		invAdd(kItemMud); +		setGrabCursorSprite(kItemMud); +		setFlag(1); +		scene01_updateHotspots(); +	} + +	if (_gameSys->getAnimationStatus(4) == 2) { +		_s01_smokeIdCtr = (_s01_smokeIdCtr + 1) % 2; +		_gameSys->setAnimation(0x86, _s01_smokeIdCtr + 20, 4); +		_gameSys->insertSequence(0x86, _s01_smokeIdCtr + 20, +			0x86, (_s01_smokeIdCtr + 1) % 2 + 20, +			kSeqSyncWait, 0, 0, 0); +	} + +	if (_gameSys->getAnimationStatus(2) == 2) { +		_s01_pigsIdCtr = (_s01_pigsIdCtr + 1) % 2; +		_gameSys->setAnimation(0x7F, _s01_pigsIdCtr + 40, 2); +		_gameSys->insertSequence(0x7F, _s01_pigsIdCtr + 40, +			0x7F, (_s01_pigsIdCtr + 1) % 2 + 40, +			kSeqSyncWait, 0, 0, 0); +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene02.cpp b/engines/gnap/scenes/scene02.cpp new file mode 100644 index 0000000000..5d740b906f --- /dev/null +++ b/engines/gnap/scenes/scene02.cpp @@ -0,0 +1,539 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSChicken		= 1, +	kHSTruck1		= 2, +	kHSTruck2		= 3, +	kHSTruckGrill	= 4, +	kHSDevice		= 5, +	kHSExitHouse	= 6, +	kHSExitBarn		= 7, +	kHSExitCreek	= 8, +	kHSExitPigpen	= 9, +	kHSWalkArea1	= 10, +	kHSWalkArea2	= 11, +	kHSWalkArea3	= 12, +	kHSWalkArea4	= 13 +}; + +enum { +	kASUseTruckNoKeys			= 0, +	kASUseGasWithTruck			= 1, +	kASUseTruckGas				= 2, +	kASUseTruckNoGas			= 3, +	kASGrabTruckGrill			= 5, +	kASLeaveScene				= 6, +	kASTalkChicken				= 7, +	kASGrabChicken				= 8, +	kASGrabChickenDone			= 9, +	kASUseTruckNoKeysDone		= 11, +	kASUseGasWithTruckDone		= 12, +	kASUseTwigWithChicken		= 16 +}; + +int GnapEngine::scene02_init() { +	_gameSys->setAnimation(0, 0, 0); +	return isFlag(9) ? 0x15A : 0x15B; +} + +void GnapEngine::scene02_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED | SF_WALKABLE); +	setHotspot(kHSChicken, 606, 455, 702, 568, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 8); +	setHotspot(kHSTruck1, 385, 258, 464, 304, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 5); +	setHotspot(kHSTruck2, 316, 224, 390, 376, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 5, 6); +	setHotspot(kHSTruckGrill, 156, 318, 246, 390, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 2, 7); +	setHotspot(kHSExitHouse, 480, 120, 556, 240, SF_EXIT_U_CURSOR, 7, 5); +	setHotspot(kHSExitBarn, 610, 0, 800, 164, SF_EXIT_U_CURSOR, 10, 5); +	setHotspot(kHSExitCreek, 780, 336, 800, 556, SF_EXIT_R_CURSOR | SF_WALKABLE, 10, 8); +	setHotspot(kHSExitPigpen, 0, 300, 20, 600, SF_EXIT_L_CURSOR | SF_WALKABLE, 0, 8); +	setHotspot(kHSWalkArea1, 92, 140, 304, 430, 0, 3, 1); +	setHotspot(kHSWalkArea2, 0, 0, 800, 380); +	setHotspot(kHSWalkArea3, 0, 0, 386, 445); +	setHotspot(kHSWalkArea4, 386, 0, 509, 410); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	if (isFlag(0)) +		_hotspots[kHSPlatypus].flags = SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR; +	_hotspotsCount = 14; +} + +void GnapEngine::scene02_run() { + +	playSound(0x1091C, 1); +	startSoundTimerC(6); + +	_s02_currChickenSequenceId = 0x14B; +	_gameSys->setAnimation(0x14B, 179, 2); +	_gameSys->insertSequence(0x14B, 179, 0, 0, kSeqNone, 0, 0, 0); + +	_s02_nextChickenSequenceId = -1; +	_timers[5] = getRandom(20) + 30; +	_timers[4] = getRandom(100) + 300; +	 +	queueInsertDeviceIcon(); +	 +	switch (_prevSceneNum) { +	case 3: +		initGnapPos(11, 6, 3); +		if (isFlag(0)) +			initBeaverPos(12, 6, 4); +		endSceneInit(); +		if (isFlag(0)) +			platypusWalkTo(9, 6, -1, 0x107C2, 1); +		gnapWalkTo(8, 6, -1, 0x107BA, 1); +		break; +	case 4: +		initGnapPos(_hotspotsWalkPos[6].x, _hotspotsWalkPos[6].y, 3); +		if (isFlag(0)) +			initBeaverPos(_hotspotsWalkPos[6].x + 1, _hotspotsWalkPos[6].y, 4); +		endSceneInit(); +		gnapWalkTo(7, 6, 0, 0x107B9, 1); +		if (isFlag(0)) +			platypusWalkTo(8, 6, 1, 0x107C2, 1); +		scene02_updateHotspots(); +		_gameSys->waitForUpdate(); +		break; +	case 47: +		clearFlag(25); +		initGnapPos(5, 6, 3); +		initBeaverPos(6, 7, 4); +		endSceneInit(); +		break; +	case 49: +		initGnapPos(5, 6, 1); +		if (isFlag(0)) +			initBeaverPos(6, 7, 0); +		endSceneInit(); +		break; +	default: +		initGnapPos(-1, 6, 1); +		if (isFlag(0)) +			initBeaverPos(-1, 7, 0); +		endSceneInit(); +		if (isFlag(0)) +			platypusWalkTo(2, 7, -1, 0x107C2, 1); +		gnapWalkTo(2, 8, -1, 0x107B9, 1); +		break; +	} +	 +	while (!_sceneDone) { +	 +		updateMouseCursor(); +	 +		updateCursorByHotspot(); +	 +		testWalk(0, 6, 7, 6, 8, 6); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene02_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0 && isFlag(0)) { +				if (_grabCursorSpriteIndex == kItemDisguise) { +					gnapUseDisguiseOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						if (isFlag(5)) +							playGnapMoan1(_platX, _platY); +						else +							playGnapScratchingHead(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSChicken: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemTwig) { +					_gnapIdleFacing = 7; +					gnapWalkTo(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y + 1, +						0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +					_gnapActionStatus = kASUseTwigWithChicken; +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y + 1, 9, 8); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan2(9, 8); +						break; +					case GRAB_CURSOR: +						_gnapIdleFacing = 1; +						if (gnapWalkTo(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1)) +							_gnapActionStatus = kASGrabChicken; +						else +							_gnapActionStatus = -1; +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 1; +						gnapWalkTo(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASTalkChicken; +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSTruck1: +		case kHSTruck2: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemKeys) { +					if (gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, 2, 2) | 0x10000, 1)) { +						setGrabCursorSprite(-1); +						invRemove(kItemKeys); +						if (isFlag(8)) +							_gnapActionStatus = kASUseTruckGas; +						else +							_gnapActionStatus = kASUseTruckNoGas; +					} +				} else if (_grabCursorSpriteIndex == kItemGas) { +					_hotspots[kHSWalkArea4].flags |= SF_WALKABLE; +					if (gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, getGnapSequenceId(gskIdle, 2, 2) | 0x10000, 1)) +						_gnapActionStatus = kASUseGasWithTruck; +					_hotspots[kHSWalkArea4].flags &= ~SF_WALKABLE; +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 2, 2); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(2, 2); +						break; +					case GRAB_CURSOR: +						if (isFlag(9)) { +							if (gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, 2, 2) | 0x10000, 1)) { +								if (isFlag(8)) +									_gnapActionStatus = kASUseTruckGas; +								else +									_gnapActionStatus = kASUseTruckNoGas; +							} +						} else { +							_gnapIdleFacing = 4; +							if (gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, 2, 2) | 0x10000, 1)) +								_gnapActionStatus = kASUseTruckNoKeys; +						} +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSTruckGrill: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 2, 4); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan2(2, 4); +						break; +					case GRAB_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASGrabTruckGrill; +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSExitHouse: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[6].x, _hotspotsWalkPos[6].y, 0, 0x107AD, 1); +				_gnapActionStatus = kASLeaveScene; +				if (isFlag(0)) +					platypusWalkTo(_hotspotsWalkPos[6].x + 1, _hotspotsWalkPos[6].y, -1, 0x107C1, 1); +				scene02_updateHotspots(); +				_newSceneNum = 4; +			} +			break; + +		case kHSExitBarn: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[7].x, _hotspotsWalkPos[7].y, 0, 0x107AD, 1); +				_gnapActionStatus = kASLeaveScene; +				if (isFlag(0)) +					platypusWalkTo(_hotspotsWalkPos[7].x + 1, _hotspotsWalkPos[7].y, -1, 0x107C1, 1); +				scene02_updateHotspots(); +				_newSceneNum = 5; +			} +			break; + +		case kHSExitCreek: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[8].x, _hotspotsWalkPos[8].y, 0, 0x107AB, 1); +				_gnapActionStatus = kASLeaveScene; +				if (isFlag(0)) +					platypusWalkTo(_hotspotsWalkPos[8].x, _hotspotsWalkPos[8].y, -1, 0x107CD, 1); +				_newSceneNum = 3; +			} +			break; + +		case kHSExitPigpen: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[9].x, _hotspotsWalkPos[9].y, 0, 0x107AF, 1); +				_gnapActionStatus = kASLeaveScene; +				if (isFlag(0)) +					platypusWalkTo(_hotspotsWalkPos[9].x, _hotspotsWalkPos[9].y, -1, 0x107CF, 1); +				_newSceneNum = 1; +			} +			break; + +		case kHSWalkArea1: +		case kHSWalkArea2: +		case kHSWalkArea3: +		case kHSWalkArea4: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; + +		default: +			if (_mouseClickState.left && _gnapActionStatus < 0) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; + +		} +	 +		scene02_updateAnimations(); +	 +		if (!isSoundPlaying(0x1091C)) +			playSound(0x1091C, 1); +	 +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0 && isFlag(0)) +				updateBeaverIdleSequence(); +			if (_gnapActionStatus < 0) +				updateGnapIdleSequence(); +			if (!_timers[4]) { +				// Update bird animation +				_timers[4] = getRandom(100) + 300; +				if (getRandom(2) != 0) +					_gameSys->insertSequence(0x156, 256, 0, 0, kSeqNone, 0, 0, 0); +				else +					_gameSys->insertSequence(0x154, 256, 0, 0, kSeqNone, 0, 0, 0); +			} +			if (!_timers[5] && _s02_nextChickenSequenceId == -1 && _gnapActionStatus != 7 && _gnapActionStatus != 8) { +				if (getRandom(6) != 0) { +					_s02_nextChickenSequenceId = 0x14B; +					_timers[5] = getRandom(20) + 30; +				} else { +					_s02_nextChickenSequenceId = 0x14D; +					_timers[5] = getRandom(20) + 50; +				} +			} +			playSoundC(); +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene02_updateHotspots(); +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene02_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		switch (_gnapActionStatus) { +		case kASUseTruckNoKeys: +			_gameSys->insertSequence(0x14E, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(0x14E, _gnapId, 0); +			_gnapSequenceId = 0x14E; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = kASUseTruckNoKeysDone; +			break; +		case kASUseGasWithTruck: +			_gameSys->insertSequence(0x151, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(0x151, _gnapId, 0); +			_gnapSequenceId = 0x151; +			_gnapSequenceDatNum = 0; +			invRemove(kItemGas); +			setGrabCursorSprite(-1); +			setFlag(8); +			_gnapActionStatus = kASUseGasWithTruckDone; +			break; +		case kASUseTruckGas: +			_timers[5] = 9999; +			_timers[4] = 9999; +			hideCursor(); +			setGrabCursorSprite(-1); +			if (!isFlag(9)) { +				_gameSys->insertSequence(0x14F, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +				_gameSys->waitForUpdate(); +				setFlag(9); +				_gnapSequenceId = 0x14F; +				_gnapSequenceDatNum = 0; +				invRemove(kItemKeys); +				setGrabCursorSprite(-1); +			} +			_newSceneNum = 47; +			_sceneDone = true; +			break; +		case kASUseTruckNoGas: +			hideCursor(); +			setGrabCursorSprite(-1); +			_timers[4] = 250; +			if (!isFlag(9)) { +				_gameSys->insertSequence(0x14F, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +				_gameSys->waitForUpdate(); +				setFlag(9); +				_gnapSequenceId = 0x14F; +				_gnapSequenceDatNum = 0; +				invRemove(kItemKeys); +				setGrabCursorSprite(-1); +			} +			_newSceneNum = 47; +			_sceneDone = true; +			setFlag(25); +			break; +		case kASGrabTruckGrill: +			switch (_s02_truckGrillCtr) { +			case 0: +				_s02_gnapTruckSequenceId = 0x158; +				break; +			case 1: +				_s02_gnapTruckSequenceId = 0x159; +				break; +			case 2: +				_s02_gnapTruckSequenceId = 0x157; +				break; +			} +			_s02_truckGrillCtr = (_s02_truckGrillCtr + 1) % 3; +			_gameSys->insertSequence(_s02_gnapTruckSequenceId, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s02_gnapTruckSequenceId, _gnapId, 0); +			_gnapSequenceId = _s02_gnapTruckSequenceId; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = -1; +			break; +		case kASLeaveScene: +			_sceneDone = true; +			break; +		case kASTalkChicken: +			_s02_nextChickenSequenceId = 0x14C; +			break; +		case kASGrabChicken: +			_s02_nextChickenSequenceId = 0x150; +			_timers[2] = 100; +			break; +		case kASGrabChickenDone: +			_gameSys->insertSequence(0x107B5, _gnapId, 0x150, 179, kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +			_gnapSequenceId = 0x7B5; +			_gnapSequenceDatNum = 1; +			_s02_currChickenSequenceId = 0x14B; +			_gameSys->setAnimation(0x14B, 179, 2); +			_gameSys->insertSequence(_s02_currChickenSequenceId, 179, 0, 0, kSeqNone, 0, 0, 0); +			_gnapActionStatus = -1; +			_timers[5] = 30; +			break; +		case kASUseTwigWithChicken: +			playGnapShowItem(5, 0, 0); +			_gameSys->insertSequence(0x155, 179, _s02_currChickenSequenceId, 179, 32, 0, 0, 0); +			_s02_currChickenSequenceId = 0x155; +			_s02_nextChickenSequenceId = -1; +			_gnapActionStatus = -1; +			break; +		case kASUseTruckNoKeysDone: +		case kASUseGasWithTruckDone: +		default: +			_gnapActionStatus = -1; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(2) == 2) { +		if (_s02_nextChickenSequenceId == 0x150) { +			_gameSys->setAnimation(_s02_nextChickenSequenceId, 179, 0); +			_gameSys->insertSequence(_s02_nextChickenSequenceId, 179, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->removeSequence(_s02_currChickenSequenceId, 179, 1); +			_s02_nextChickenSequenceId = -1; +			_s02_currChickenSequenceId = -1; +			_gnapActionStatus = kASGrabChickenDone; +			_timers[5] = 500; +		} else if (_s02_nextChickenSequenceId == 0x14C) { +			_gameSys->setAnimation(_s02_nextChickenSequenceId, 179, 2); +			_gameSys->insertSequence(_s02_nextChickenSequenceId, 179, _s02_currChickenSequenceId, 179, kSeqSyncWait, 0, 0, 0); +			_s02_currChickenSequenceId = _s02_nextChickenSequenceId; +			_s02_nextChickenSequenceId = -1; +			_gnapActionStatus = -1; +		} else if (_s02_nextChickenSequenceId != -1) { +			_gameSys->setAnimation(_s02_nextChickenSequenceId, 179, 2); +			_gameSys->insertSequence(_s02_nextChickenSequenceId, 179, _s02_currChickenSequenceId, 179, kSeqSyncWait, 0, 0, 0); +			_s02_currChickenSequenceId = _s02_nextChickenSequenceId; +			_s02_nextChickenSequenceId = -1; +		} +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene03.cpp b/engines/gnap/scenes/scene03.cpp new file mode 100644 index 0000000000..6f191dc6e3 --- /dev/null +++ b/engines/gnap/scenes/scene03.cpp @@ -0,0 +1,517 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus			= 0, +	kHSGrass			= 1, +	kHSExitTruck		= 2, +	kHSCreek			= 3, +	kHSTrappedPlatypus	= 4, +	kHSDevice			= 5, +	kHSWalkAreas1		= 6, +	kHSWalkAreas2		= 7, +	kHSPlatypusWalkArea	= 8, +	kHSWalkAreas3		= 9 +}; + +enum { +	kASLeaveScene			= 0, +	kASFreePlatypus			= 1, +	kASHypnotizePlat		= 2, +	kASHypnotizeScaredPlat	= 3, +	kASFreePlatypusDone		= 4, +	kASGrabPlatypus			= 5, +	kASGrabCreek			= 6, +	kASGrabCreekDone		= 7, +	kASGrabScaredPlatypus	= 8 +}; + +int GnapEngine::scene03_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	_gameSys->setAnimation(0, 0, 5); +	return 0x1CC; +} + +void GnapEngine::scene03_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED | SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSGrass, 646, 408, 722, 458, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 9, 6); +	setHotspot(kHSExitTruck, 218, 64, 371, 224, SF_EXIT_U_CURSOR | SF_WALKABLE, 4, 4); +	setHotspot(kHSCreek, 187, 499, 319, 587, SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 7); +	setHotspot(kHSTrappedPlatypus, 450, 256, 661, 414, SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 2, 5); +	setHotspot(kHSWalkAreas1, 0, 500, 300, 600); +	setHotspot(kHSWalkAreas2, 300, 447, 800, 600); +	setHotspot(kHSPlatypusWalkArea, 235, 0, 800, 600); +	setHotspot(kHSWalkAreas3, 0, 0, 800, 354); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	if (isFlag(0)) +		_hotspots[kHSPlatypus].flags = SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR; +	if (isFlag(6)) +		_hotspots[kHSGrass].flags = SF_WALKABLE | SF_DISABLED; +	if (isFlag(0)) +		_hotspots[kHSTrappedPlatypus].flags = SF_DISABLED; +	if (isFlag(0) || _s03_platypusHypnotized) +		_hotspots[kHSPlatypusWalkArea].flags |= SF_WALKABLE; +	_hotspotsCount = 10; +} + +void GnapEngine::scene03_run() { + +	playSound(0x10925, 1); +	 +	startSoundTimerC(7); +	 +	_gameSys->insertSequence(0x1CA, 251, 0, 0, kSeqLoop, 0, 0, 0); +	_gameSys->insertSequence(0x1CB, 251, 0, 0, kSeqLoop, 0, 0, 0); +	 +	_s03_platypusHypnotized = false; +	 +	initGnapPos(3, 4, 1); +	 +	_gameSys->insertSequence(0x1C6, 253, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s03_currFrogSequenceId = 0x1C6; +	_s03_nextFrogSequenceId = -1; +	_gameSys->setAnimation(0x1C6, 253, 2); +	 +	_timers[6] = getRandom(20) + 30; +	_timers[4] = getRandom(100) + 300; +	_timers[5] = getRandom(100) + 200; +	 +	if (isFlag(0)) { +		initBeaverPos(5, 4, 0); +	} else { +		_timers[1] = getRandom(40) + 20; +		_gameSys->setAnimation(0x1C2, 99, 1); +		_gameSys->insertSequence(0x1C2, 99, 0, 0, kSeqNone, 0, 0, 0); +		_beaverSequenceId = 0x1C2; +		_beaverSequenceDatNum = 0; +	} +	 +	_gameSys->insertSequence(0x1C4, 255, 0, 0, kSeqNone, 0, 0, 0); +	 +	if (!isFlag(6)) +		_gameSys->insertSequence(0x1B2, 253, 0, 0, kSeqNone, 0, 0, 0); +	 +	queueInsertDeviceIcon(); +	 +	endSceneInit(); +	 +	if (isFlag(0)) +		platypusWalkTo(4, 7, -1, 0x107C2, 1); +	gnapWalkTo(3, 6, -1, 0x107B9, 1); +	 +	while (!_sceneDone) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSPlatypus: +			if (_gnapActionStatus < 0 && isFlag(0)) { +				if (_grabCursorSpriteIndex == kItemDisguise) { +					gnapUseDisguiseOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						if (isFlag(5)) +							playGnapMoan1(_platX, _platY); +						else +							playGnapScratchingHead(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSGrass: +			if (_gnapActionStatus < 0) { +				if (isFlag(6)) { +					gnapWalkTo(-1, -1, -1, -1, 1); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowItem(_grabCursorSpriteIndex, 9, 6); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(9, 6); +						break; +					case GRAB_CURSOR: +						playGnapPullOutDevice(9, 6); +						playGnapUseDevice(0, 0); +						_gameSys->insertSequence(0x1B3, 253, 0x1B2, 253, kSeqSyncWait, 0, 0, 0); +						_gameSys->setAnimation(0x1B3, 253, 5); +						_hotspots[kHSGrass].flags |= SF_WALKABLE | SF_DISABLED; +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSExitTruck: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				_hotspots[kHSPlatypusWalkArea].flags |= SF_WALKABLE; +				gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, 0x107AD, 1); +				_gnapActionStatus = kASLeaveScene; +				if (isFlag(0)) +					platypusWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, -1, 0x107C2, 1); +				_hotspots[kHSPlatypusWalkArea].flags &= ~SF_WALKABLE; +				if (_cursorValue == 1) +					_newSceneNum = 2; +				else +					_newSceneNum = 33; +			} +			break; + +		case kHSCreek: +			if (_gnapActionStatus == -1) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan2(2, 8); +						break; +					case GRAB_CURSOR: +						if (!isFlag(0)) +							_hotspots[kHSPlatypusWalkArea].flags |= SF_WALKABLE; +						if (gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, _hotspotsWalkPos[3].x + 1, _hotspotsWalkPos[3].y + 1) | 0x10000, 1)) +							_gnapActionStatus = kASGrabCreek; +						if (!isFlag(0)) +							_hotspots[kHSPlatypusWalkArea].flags &= ~SF_WALKABLE; +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSTrappedPlatypus: +			if (_gnapActionStatus < 0) { +				if (isFlag(0)) { +					gnapWalkTo(-1, -1, -1, -1, 1); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowItem(_grabCursorSpriteIndex, 8, 4); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(8, 4); +						break; +					case GRAB_CURSOR: +						if (_s03_platypusHypnotized) { +							gnapWalkTo(7, 6, 0, 0x107B5, 1); +							_gnapActionStatus = kASFreePlatypus; +						} else { +							gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +							if (_s03_platypusScared) +								_gnapActionStatus = kASGrabScaredPlatypus; +							else +								_gnapActionStatus = kASGrabPlatypus; +						} +						break; +					case TALK_CURSOR: +						if (_s03_platypusHypnotized) { +							playGnapBrainPulsating(8, 4); +						} else { +							_gnapIdleFacing = 1; +							gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +							if (_s03_platypusScared) +								_gnapActionStatus = kASHypnotizeScaredPlat; +							else +								_gnapActionStatus = kASHypnotizePlat; +						} +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene03_updateHotspots(); +			} +			break; + +		case kHSWalkAreas1: +		case kHSWalkAreas2: +		case kHSWalkAreas3: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; + +		case kHSPlatypusWalkArea: +			if (_gnapActionStatus < 0) { +				if (isFlag(0) || _s03_platypusHypnotized) { +					gnapWalkTo(-1, -1, -1, -1, 1); +				} else { +					gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, 0x107B5, 1); +					if (_s03_platypusScared) +						_gnapActionStatus = kASGrabScaredPlatypus; +					else +						_gnapActionStatus = kASGrabPlatypus; +				} +			} +			break; +			 +		default: +			if (_mouseClickState.left && _gnapActionStatus < 0) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +			 +		} + +		scene03_updateAnimations(); +	 +		if (!isSoundPlaying(0x10925)) +			playSound(0x10925, 1); +	 +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0 && isFlag(0)) +				updateBeaverIdleSequence(); +			if (_gnapActionStatus < 0) +				updateGnapIdleSequence(); +			if (!_timers[1] && !_s03_platypusScared) { +				_timers[1] = getRandom(40) + 20; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && !isFlag(0) && !_s03_platypusHypnotized) +					_s03_nextPlatSequenceId = 450; +			} +			if (!_timers[6]) { +				_timers[6] = getRandom(20) + 30; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s03_nextFrogSequenceId == -1) { +					if (getRandom(5) == 1) +						_s03_nextFrogSequenceId = 0x1C6; +					else +						_s03_nextFrogSequenceId = 0x1C7; +				} +			} +			if (!_timers[4]) { +				// Update bird animation +				_timers[4] = getRandom(100) + 300; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0) +					_gameSys->insertSequence(getRandom(2) != 0 ? 0x1C8 : 0x1C3, 253, 0, 0, kSeqNone, 0, 0, 0); +			} +			if (!_timers[5]) { +				_timers[5] = getRandom(100) + 200; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0) { +					_gameSys->setAnimation(0x1C5, 253, 4); +					_gameSys->insertSequence(0x1C5, 253, 0, 0, kSeqNone, 0, 0, 0); +				} +			} +			playSoundC(); +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene03_updateHotspots(); +			_timers[5] = getRandom(100) + 200; +			_timers[4] = getRandom(100) + 300; +			_timers[6] = getRandom(20) + 30; +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene03_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASLeaveScene: +			_sceneDone = true; +			break; +		case kASFreePlatypus: +			_s03_nextPlatSequenceId = 0x1BC; +			break; +		case kASFreePlatypusDone: +			_gnapActionStatus = -1; +			_platX = 6; +			_platY = 6; +			_beaverFacing = 4; +			_beaverId = 120; +			_gameSys->insertSequence(0x107CA, _beaverId, 0x1BC, 99, +				kSeqSyncWait, 0, 75 * _platX - _platGridX, 48 * _platY - _platGridY); +			_gameSys->insertSequence(0x1B7, 99, 0, 0, kSeqNone, 0, 0, 0); +			_beaverSequenceDatNum = 1; +			_beaverSequenceId = 0x7CA; +			setFlag(0); +			_s03_nextPlatSequenceId = -1; +			scene03_updateHotspots(); +			break; +		case kASHypnotizePlat: +			playGnapBrainPulsating(0, 0); +			addFullScreenSprite(0x106, 255); +			_gameSys->setAnimation(0x1C9, 256, 1); +			_gameSys->insertSequence(0x1C9, 256, 0, 0, kSeqNone, 0, 0, 0); +			while (_gameSys->getAnimationStatus(1) != 2) +				gameUpdateTick(); +			removeFullScreenSprite(); +			_gameSys->setAnimation(0x1BA, 99, 1); +			_gameSys->insertSequence(0x1BA, 99, _beaverSequenceId | (_beaverSequenceDatNum << 16), 99, 32, 0, 0, 0); +			_beaverSequenceDatNum = 0; +			_beaverSequenceId = 0x1BA; +			_gnapActionStatus = -1; +			_s03_platypusHypnotized = true; +			scene03_updateHotspots(); +			break; +		case kASHypnotizeScaredPlat: +			playGnapBrainPulsating(0, 0); +			_gameSys->insertSequence(0x1BF, 99, _beaverSequenceId | (_beaverSequenceDatNum << 16), 99, 32, 0, 0, 0); +			_gameSys->setAnimation(0x1BF, 99, 1); +			while (_gameSys->getAnimationStatus(1) != 2) +				gameUpdateTick(); +			addFullScreenSprite(0x106, 255); +			_gameSys->setAnimation(0x1C9, 256, 1); +			_gameSys->insertSequence(0x1C9, 256, 0, 0, kSeqNone, 0, 0, 0); +			while (_gameSys->getAnimationStatus(1) != 2) +				gameUpdateTick(); +			removeFullScreenSprite(); +			_gameSys->setAnimation(0x1BA, 99, 1); +			_gameSys->insertSequence(0x1BA, 99, 447, 99, kSeqSyncWait, 0, 0, 0); +			_beaverSequenceDatNum = 0; +			_beaverSequenceId = 0x1BA; +			_gnapActionStatus = -1; +			_s03_platypusHypnotized = true; +			scene03_updateHotspots(); +			break; +		case kASGrabPlatypus: +			_s03_nextPlatSequenceId = 0x1BD; +			_s03_platypusHypnotized = false; +			break; +		case kASGrabScaredPlatypus: +			_s03_nextPlatSequenceId = 0x1C0; +			_s03_platypusHypnotized = false; +			break; +		case kASGrabCreek: +			_gameSys->insertSequence(0x1B4, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(0x1B4, _gnapId, 0); +			_gnapSequenceId = 0x1B4; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = kASGrabCreekDone; +			break; +		default: +			_gnapActionStatus = -1; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(1) == 2) { +		if (_s03_nextPlatSequenceId == 0x1BD || _s03_nextPlatSequenceId == 0x1C0) { +			_gameSys->setAnimation(0, 0, 1); +			_s03_platypusScared = true; +			_gameSys->insertSequence(0x1B5, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(_s03_nextPlatSequenceId, 99, _beaverSequenceId | (_beaverSequenceDatNum << 16), 99, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x1B5; +			_gnapSequenceDatNum = 0; +			_gnapIdleFacing = 0; +			_beaverSequenceId = _s03_nextPlatSequenceId; +			_beaverSequenceDatNum = 0; +			_gameSys->setAnimation(_s03_nextPlatSequenceId, 99, 1); +			_s03_nextPlatSequenceId = -1; +			_gnapActionStatus = -1; +		} else if (_s03_nextPlatSequenceId == 0x1BC) { +			_gnapX = 3; +			_gnapY = 6; +			_gameSys->insertSequence(0x1B6, 120, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x1BC, 99, _beaverSequenceId | (_beaverSequenceDatNum << 16), 99, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(0x1BC, 99, 0); +			_gnapId = 20 * _gnapY; +			_gnapSequenceId = 0x1B6; +			_gnapSequenceDatNum = 0; +			_gnapIdleFacing = 0; +			_gnapActionStatus = kASFreePlatypusDone; +			_s03_nextPlatSequenceId = -1; +		} else if (_s03_nextPlatSequenceId == 0x1C2 && !_s03_platypusScared) { +			_gameSys->setAnimation(0, 0, 1); +			_gameSys->insertSequence(0x1C2, 99, _beaverSequenceId | (_beaverSequenceDatNum << 16), 99, kSeqSyncWait, 0, 0, 0); +			_beaverSequenceId = 0x1C2; +			_beaverSequenceDatNum = 0; +			_gameSys->setAnimation(0x1C2, 99, 1); +			_s03_nextPlatSequenceId = -1; +		} else if (_s03_nextPlatSequenceId == -1 && _s03_platypusScared && !_s03_platypusHypnotized) { +			_gameSys->setAnimation(0, 0, 1); +			_gameSys->setAnimation(0x1BE, 99, 1); +			_gameSys->insertSequence(0x1BE, 99, _beaverSequenceId | (_beaverSequenceDatNum << 16), 99, kSeqSyncWait, 0, 0, 0); +			_beaverSequenceId = 0x1BE; +			_beaverSequenceDatNum = 0; +			_s03_nextPlatSequenceId = -1; +		} +	} +	 +	if (_gameSys->getAnimationStatus(2) == 2 && _s03_nextFrogSequenceId != -1) { +		_gameSys->setAnimation(_s03_nextFrogSequenceId, 253, 2); +		_gameSys->insertSequence(_s03_nextFrogSequenceId, 253, _s03_currFrogSequenceId, 253, kSeqSyncWait, 0, 0, 0); +		_s03_currFrogSequenceId = _s03_nextFrogSequenceId; +		_s03_nextFrogSequenceId = -1; +	} +	 +	if (_gameSys->getAnimationStatus(5) == 2) { +		_gameSys->setAnimation(0, 0, 5); +		invAdd(kItemGrass); +		setGrabCursorSprite(kItemGrass); +		setFlag(6); +		scene03_updateHotspots(); +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene04.cpp b/engines/gnap/scenes/scene04.cpp new file mode 100644 index 0000000000..bc5ee855d3 --- /dev/null +++ b/engines/gnap/scenes/scene04.cpp @@ -0,0 +1,571 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSTwig			= 1, +	kHSDog			= 2, +	kHSAxe			= 3, +	kHSDoor			= 4, +	kHSExitTruck	= 5, +	kHSDevice		= 6, +	kHSWindow		= 7, +	kHSExitBarn		= 8, +	kHSWalkArea1	= 9, +	kHSWalkArea2	= 10 +}; + +enum { +	kASOpenDoor				= 1, +	kASGetKeyFirst			= 2, +	kASGetKeyAnother		= 3, +	kASLeaveScene			= 4, +	kASGetKeyFirstDone		= 6, +	kASGetKeyFirst2			= 7, +	kASGetKeyAnother2		= 8, +	kASGetKeyAnotherDone	= 9, +	kASOpenDoorDone			= 10, +	kASGrabDog				= 12, +	kASGrabAxe				= 13 +}; + +int GnapEngine::scene04_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	_gameSys->setAnimation(0, 0, 2); +	return 0x214; +} + +void GnapEngine::scene04_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED | SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSTwig, 690, 394, 769, 452, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 9, 6); +	setHotspot(kHSDog, 550, 442, 680, 552, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 8); +	setHotspot(kHSAxe, 574, 342, 680, 412, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 7); +	setHotspot(kHSDoor, 300, 244, 386, 410, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 7); +	setHotspot(kHSExitTruck, 226, 580, 688, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9); +	setHotspot(kHSWindow, 121, 295, 237, 342, SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 7); +	setHotspot(kHSExitBarn, 585, 154, 800, 276, SF_EXIT_U_CURSOR, 10, 8); +	setHotspot(kHSWalkArea1, 0, 0, 562, 461); +	setHotspot(kHSWalkArea2, 562, 0, 800, 500); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	if (isFlag(0)) +		_hotspots[kHSPlatypus].flags = SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR; +	if (isFlag(3)) +		_hotspots[kHSTwig].flags = SF_WALKABLE | SF_DISABLED; +	if (isFlag(26) || _cursorValue == 1) +		_hotspots[kHSAxe].flags = SF_DISABLED; +	_hotspotsCount = 11; +} + +void GnapEngine::scene04_run() { + +	playSound(0x1091C, 1); +	startSoundTimerC(4); + +	_gameSys->insertSequence(0x210, 139 - _s04_dogIdCtr, 0, 0, kSeqNone, 0, 0, 0); + +	_s04_currDogSequenceId = 0x210; +	_s04_nextDogSequenceId = -1; +	 +	_gameSys->setAnimation(0x210, 139 - _s04_dogIdCtr, 3); +	_s04_dogIdCtr = (_s04_dogIdCtr + 1) % 2; +	_timers[6] = getRandom(20) + 60; +	_timers[5] = getRandom(150) + 300; +	_timers[7] = getRandom(150) + 200; +	_timers[8] = getRandom(150) + 400; + +	if (!isFlag(26) && _cursorValue == 4) +		_gameSys->insertSequence(0x212, 100, 0, 0, kSeqNone, 0, 0, 0); +	 +	if (!isFlag(3)) +		_gameSys->insertSequence(0x1FE, 100, 0, 0, kSeqNone, 0, 0, 0); +	 +	queueInsertDeviceIcon(); +	 +	if (isFlag(10)) { +		_timers[3] = 300; +		// TODO setCursor((LPCSTR)IDC_WAIT); +		setGrabCursorSprite(kItemKeys); +		_gnapX = 4; +		_gnapY = 7; +		_gnapId = 140; +		_platX = 6; +		_platY = 7; +		_beaverId = 141; +		_gameSys->insertSequence(0x107B5, 140, 0, 0, kSeqNone, 0, 300 - _gnapGridX, 336 - _gnapGridY); +		_gameSys->insertSequence(0x20C, 141, 0, 0, kSeqNone, 0, 0, 0); +		_gameSys->insertSequence(0x208, 121, 0, 0, kSeqNone, 0, 0, 0); +		_gameSys->insertSequence(0x209, 121, 0x208, 121, kSeqSyncWait, 0, 0, 0); +		endSceneInit(); +		invRemove(kItemDisguise); +		invAdd(kItemKeys); +		setFlag(5); +		clearFlag(10); +		_beaverSequenceId = 0x20C; +		_beaverSequenceDatNum = 0; +		_beaverFacing = 1; +		_gnapSequenceId = 0x7B5; +		_gnapSequenceDatNum = 1; +		_gameSys->waitForUpdate(); +	} else { +		_gameSys->insertSequence(0x209, 121, 0, 0, kSeqNone, 0, 0, 0); +		if (_prevSceneNum == 2) { +			initGnapPos(5, 11, 7); +			if (isFlag(0)) +				initBeaverPos(6, 11, 5); +			endSceneInit(); +			if (isFlag(0)) +				platypusWalkTo(5, 8, -1, 0x107C2, 1); +			gnapWalkTo(6, 9, -1, 0x107BA, 1); +		} else if (_prevSceneNum == 38) { +			initGnapPos(5, 7, 1); +			initBeaverPos(4, 7, 0); +			endSceneInit(); +		} else { +			initGnapPos(12, 9, 1); +			if (isFlag(0)) +				initBeaverPos(12, 8, 0); +			endSceneInit(); +			if (isFlag(0)) +				platypusWalkTo(9, 8, -1, 0x107C2, 1); +		gnapWalkTo(9, 9, -1, 0x107BA, 1); +		} +	} +	 +	while (!_sceneDone) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +		 +		testWalk(0, 4, -1, -1, -1, -1); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene04_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0 && isFlag(0)) { +				if (_grabCursorSpriteIndex == kItemDisguise) { +					gnapUseDisguiseOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						if (isFlag(5)) +							playGnapMoan1(_platX, _platY); +						else +							playGnapScratchingHead(_platX, _platY); +						break; +					case GRAB_CURSOR: +						if (_cursorValue == 4) +							gnapKissPlatypus(0); +						else +							playGnapMoan1(_platX, _platY); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSTwig: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowItem(_grabCursorSpriteIndex, 9, 6); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y); +						break; +					case GRAB_CURSOR: +						playGnapPullOutDevice(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y); +						playGnapUseDevice(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y); +						_gameSys->insertSequence(0x1FD, 100, 510, 100, kSeqSyncWait, 0, 0, 0); +						_gameSys->setAnimation(0x1FD, 100, 2); +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSAxe: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 9, 5); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan2(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y); +						break; +					case GRAB_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASGrabAxe; +						setFlag(26); +						scene04_updateHotspots(); +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSDog: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 9, 7); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						if (gnapWalkTo(_gnapX, _gnapY, 0, -1, 1)) { +							playGnapMoan2(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y); +							_s04_nextDogSequenceId = 0x20F; +						} +						break; +					case GRAB_CURSOR: +						_gnapIdleFacing = 1; +						if (gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1)) +							_gnapActionStatus = kASGrabDog; +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 1; +						if (gnapWalkTo(_gnapX, _gnapY, 0, -1, 1)) { +							playGnapBrainPulsating(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y); +							_s04_nextDogSequenceId = 0x20E; +						} +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSDoor: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 4, 3); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +					case PLAT_CURSOR: +						playGnapScratchingHead(4, 3); +						break; +					case GRAB_CURSOR: +						if (_cursorValue == 1) { +							gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, 0x107BC, 1); +							_gnapActionStatus = kASOpenDoor; +							_timers[5] = 300; +							_gnapIdleFacing = 5; +						} else { +							_isLeavingScene = true; +							gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, 0x107BC, 1); +							_gnapActionStatus = kASLeaveScene; +							_newSceneNum = 38; +						} +						break; +					case TALK_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSExitTruck: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[5].x, _hotspotsWalkPos[5].y, 0, 0x107AE, 1); +				_gnapActionStatus = kASLeaveScene; +				if (isFlag(0)) +					platypusWalkTo(_hotspotsWalkPos[5].x, _hotspotsWalkPos[5].y, -1, 0x107C7, 1); +				if (_cursorValue == 1) +					_newSceneNum = 2; +				else +					_newSceneNum = 33; +			} +			break; +		 +		case kHSWindow: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 2, 3); +				} else if (isFlag(5)) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						if (gnapWalkTo(_hotspotsWalkPos[7].x, _hotspotsWalkPos[7].y, 0, getGnapSequenceId(gskIdle, 10, 2) | 0x10000, 1)) { +							if (_s04_triedWindow) { +								_gnapActionStatus = kASGetKeyAnother; +							} else { +								_gnapActionStatus = kASGetKeyFirst; +								_s04_triedWindow = true; +							} +						} +						break; +					case GRAB_CURSOR: +						playGnapScratchingHead(_hotspotsWalkPos[7].x, _hotspotsWalkPos[7].y); +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSExitBarn: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[8].x, _hotspotsWalkPos[8].y, 0, 0x107AB, 1); +				_gnapActionStatus = kASLeaveScene; +				if (isFlag(0)) +					platypusWalkTo(_hotspotsWalkPos[8].x, _hotspotsWalkPos[8].y + 1, -1, 0x107C1, 1); +				if (_cursorValue == 1) +					_newSceneNum = 5; +				else +					_newSceneNum = 35; +			} +			break; +		 +		case kHSWalkArea1: +		case kHSWalkArea2: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; +			 +		default: +			if (_mouseClickState.left && _gnapActionStatus < 0) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +			      	 +		} +	 +		scene04_updateAnimations(); +	 +		if (!isSoundPlaying(0x1091C)) +			playSound(0x1091C, 1); +	 +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0 && isFlag(0)) +				beaverSub426234(); +			if (_gnapActionStatus < 0) +				updateGnapIdleSequence2(); +			if (!_timers[5]) { +				_timers[5] = getRandom(150) + 300; +				if (_gnapActionStatus < 0) +					_gameSys->insertSequence(0x20D, 79, 0, 0, kSeqNone, 0, 0, 0); +			} +			if (!_timers[7]) { +				_timers[7] = getRandom(150) + 200; +				_gameSys->insertSequence(0x1FC, 59, 0, 0, kSeqNone, 0, 0, 0); +			} +			if (!_timers[6]) { +				_timers[6] = getRandom(20) + 60; +				if (_s04_nextDogSequenceId == -1) +					_s04_nextDogSequenceId = 0x210; +			} +			if (!_timers[8]) { +				_timers[8] = getRandom(150) + 400; +				_gameSys->insertSequence(0x213, 20, 0, 0, kSeqNone, 0, 0, 0); +			} +			playSoundC(); +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene04_updateHotspots(); +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene04_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASLeaveScene: +			_sceneDone = true; +			break; +		case kASOpenDoor: +			_gameSys->insertSequence(0x205, _gnapId, 0, 0, kSeqNone, 0, 0, 0); +			_gameSys->insertSequence(0x207, 121, 521, 121, kSeqSyncWait, 0, 0, 0); +			_gnapX = 6; +			_gnapY = 7; +			_gameSys->insertSequence(0x107B5, _gnapId, +				makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +				kSeqSyncWait, getSequenceTotalDuration(0x205) - 1, 450 - _gnapGridX, 336 - _gnapGridY); +			_gameSys->setAnimation(0x107B5, _gnapId, 0); +			_gnapSequenceId = 0x7B5; +			_gnapSequenceDatNum = 1; +			_gnapActionStatus = kASOpenDoorDone; +			break; +		case kASOpenDoorDone: +			_gameSys->insertSequence(0x209, 121, 0x207, 121, kSeqSyncWait, 0, 0, 0); +			_gnapActionStatus = -1; +			break; +		case kASGetKeyFirst: +			_gameSys->insertSequence(0x204, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(0x204, _gnapId, 0); +			_gnapSequenceId = 0x204; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = kASGetKeyFirst2; +			break; +		case kASGetKeyFirst2: +			_gameSys->insertSequence(0x206, 255, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x1FF, 256, 0, 0, kSeqNone, 0, 0, 0); +			_gameSys->insertSequence(0x20B, 256, 0, 0, kSeqNone, 0, 0, 0); +			_gameSys->setAnimation(0x20B, 256, 0); +			_gnapSequenceId = 0x206; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = kASGetKeyFirstDone; +			break; +		case kASGetKeyFirstDone: +			_gameSys->requestRemoveSequence(0x1FF, 256); +			_gameSys->requestRemoveSequence(0x20B, 256); +			_gameSys->insertSequence(0x107B5, _gnapId, +				makeRid(_gnapSequenceDatNum, _gnapSequenceId), 255, +				kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +			_gnapIdleFacing = 1; +			_gnapSequenceId = 0x7B5; +			_gnapSequenceDatNum = 1; +			_gnapActionStatus = -1; +			break; +		case kASGetKeyAnother: +			_gameSys->insertSequence(0x202, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(0x202, _gnapId, 0); +			_gnapSequenceId = 0x202; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = kASGetKeyAnother2; +			break; +		case kASGetKeyAnother2: +			_gameSys->insertSequence(0x203, 255, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x1FF, 256, 0, 0, kSeqNone, 0, 0, 0); +			_gameSys->insertSequence(0x20A, 256, 0, 0, kSeqNone, 0, 0, 0); +			_gameSys->setAnimation(0x20A, 256, 0); +			_gnapSequenceId = 0x203; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = kASGetKeyAnotherDone; +			break; +		case kASGetKeyAnotherDone: +			_gameSys->removeSequence(0x1FF, 256, 1); +			_gameSys->removeSequence(0x20A, 256, 1); +			_gameSys->insertSequence(0x107B5, _gnapId, +				makeRid(_gnapSequenceDatNum, _gnapSequenceId), 255, +				kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +			_gnapSequenceId = 0x7B5; +			_gnapSequenceDatNum = 1; +			_gnapIdleFacing = 1; +			_gnapActionStatus = -1; +			break; +		case kASGrabDog: +			_s04_nextDogSequenceId = 0x201; +			break; +		case kASGrabAxe: +			_gameSys->insertSequence(0x211, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->requestRemoveSequence(0x212, 100); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x211; +			_gnapActionStatus = -1; +			break; +		default: +			_gnapActionStatus = -1; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(2) == 2) { +		_gameSys->setAnimation(0, 0, 2); +		invAdd(kItemTwig); +		setGrabCursorSprite(kItemTwig); +		setFlag(3); +		scene04_updateHotspots(); +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2) { +		if (_s04_nextDogSequenceId == 0x201) { +			_gameSys->insertSequence(_s04_nextDogSequenceId, 139 - _s04_dogIdCtr, +				_s04_currDogSequenceId, 139 - (_s04_dogIdCtr + 1) % 2, +				kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x200, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s04_nextDogSequenceId, 139 - _s04_dogIdCtr, 3); +			_s04_dogIdCtr = (_s04_dogIdCtr + 1) % 2; +			_s04_currDogSequenceId = 0x201; +			_gnapSequenceId = 0x200; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = -1; +			_timers[6] = getRandom(20) + 60; +			_s04_nextDogSequenceId = -1; +		} else if (_s04_nextDogSequenceId != -1) { +			_gameSys->insertSequence(_s04_nextDogSequenceId, 139 - _s04_dogIdCtr, +				_s04_currDogSequenceId, 139 - (_s04_dogIdCtr + 1) % 2, +				kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s04_nextDogSequenceId, 139 - _s04_dogIdCtr, 3); +			_s04_dogIdCtr = (_s04_dogIdCtr + 1) % 2; +			_s04_currDogSequenceId = _s04_nextDogSequenceId; +			_s04_nextDogSequenceId = -1; +		} +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene05.cpp b/engines/gnap/scenes/scene05.cpp new file mode 100644 index 0000000000..fdc6ba16fe --- /dev/null +++ b/engines/gnap/scenes/scene05.cpp @@ -0,0 +1,467 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSHaystack		= 1, +	kHSPadlock		= 2, +	kHSLadder		= 3, +	kHSExitHouse	= 4, +	kHSChicken		= 5, +	kHSDevice		= 6, +	kHSWalkArea1	= 7, +	kHSWalkArea2	= 8, +	kHSWalkArea3	= 9 +}; + +enum { +	kASPlatSearchHaystack		= 0, +	kASTryPickPadlock			= 1, +	kASPickPadlock				= 2, +	kASTalkChicken				= 3, +	kASGrabChicken				= 4, +	kASGrabLadder				= 5, +	kASEnterBarn				= 6, +	kASUseTwigWithChicken		= 11, +	kASLeaveScene				= 12 +}; + +int GnapEngine::scene05_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	_gameSys->setAnimation(0, 0, 3); +	return isFlag(7) ? 0x151 : 0x150; +} + +void GnapEngine::scene05_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED | SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSHaystack, 236, 366, 372, 442, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 5, 7); +	setHotspot(kHSPadlock, 386, 230, 626, 481, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 5, 7); +	setHotspot(kHSLadder, 108, 222, 207, 444, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 4, 7); +	setHotspot(kHSExitHouse, 0, 395, 20, 600, SF_EXIT_L_CURSOR | SF_WALKABLE, 0, 8); +	setHotspot(kHSChicken, 612, 462, 722, 564, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 8); +	setHotspot(kHSWalkArea1, 104, 0, 421, 480); +	setHotspot(kHSWalkArea2, 422, 0, 800, 487); +	setHotspot(kHSWalkArea3, 0, 0, 104, 499); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	if (isFlag(0)) +		_hotspots[kHSPlatypus].flags = SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR; +	if (isFlag(7)) +		_hotspots[kHSPadlock].flags = SF_EXIT_U_CURSOR; +	_hotspotsCount = 10; +} + +void GnapEngine::scene05_run() { + +	playSound(0x1091C, 1); +	startSoundTimerC(7); +	 +	_s05_currChickenSequenceId = 0x142; +	_gameSys->setAnimation(0x142, 100, 3); +	_gameSys->insertSequence(0x142, 100, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s05_nextChickenSequenceId = -1; + +	_timers[5] = getRandom(10) + 30; +	_timers[6] = getRandom(150) + 300; + +	if (isFlag(7)) +		_gameSys->insertSequence(0x14A, 141, 0, 0, kSeqNone, 0, 0, 0); +	 +	queueInsertDeviceIcon(); +	 +	if (_prevSceneNum != 6 && _prevSceneNum != 36) { +		initGnapPos(-1, 8, 1); +		if (isFlag(0)) +			initBeaverPos(-1, 9, 0); +		endSceneInit(); +		if (isFlag(0)) +			platypusWalkTo(2, 8, -1, 0x107C2, 1); +		gnapWalkTo(2, 9, -1, 0x107B9, 1); +	} else { +		initGnapPos(6, 8, 1); +		if (isFlag(0)) +			initBeaverPos(7, 9, 0); +		endSceneInit(); +	} +	 +	while (!_sceneDone) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 12, -1, -1, -1, -1); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene05_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0 && isFlag(0)) { +				if (_grabCursorSpriteIndex == kItemDisguise) { +					gnapUseDisguiseOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						if (isFlag(5)) +							playGnapMoan1(_platX, _platY); +						else +							playGnapScratchingHead(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSHaystack: +			if (_gnapActionStatus < 0 && _beaverActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[1].x - 2, _hotspotsWalkPos[1].y, 4, 5); +				} else if (isFlag(2)) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y - 1); +						break; +					case GRAB_CURSOR: +					case TALK_CURSOR: +						playGnapImpossible(0, 0); +						break; +					case PLAT_CURSOR: +						if (isFlag(0)) { +							gnapUseDeviceOnBeaver(); +							if (platypusWalkTo(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y, 1, 0x107C2, 1)) { +								_beaverActionStatus = kASPlatSearchHaystack; +								_beaverFacing = 4; +							} +							if (_gnapX == 4 && (_gnapY == 8 || _gnapY == 7)) +								gnapWalkStep(); +							playGnapIdle(_platX, _platY); +						} +						break; +					} +				} +			} +			break; + +		case kHSChicken: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemTwig) { +					_gnapIdleFacing = 7; +					gnapWalkTo(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y + 1, +						0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +					_gnapActionStatus = kASUseTwigWithChicken; +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y + 1, 9, 7); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan2(9, 7); +						break; +					case GRAB_CURSOR: +						_gnapIdleFacing = 1; +						gnapWalkTo(_hotspotsWalkPos[5].x, _hotspotsWalkPos[5].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASGrabChicken; +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 1; +						gnapWalkTo(_hotspotsWalkPos[5].x, _hotspotsWalkPos[5].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASTalkChicken; +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSLadder: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 2, 5); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan2(2, 4); +						break; +					case GRAB_CURSOR: +						_gnapIdleFacing = 3; +						gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASGrabLadder; +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSPadlock: +			if (isFlag(7)) { +				_isLeavingScene = true; +				gnapWalkTo(_hotspotsWalkPos[2].x - 1, _hotspotsWalkPos[2].y + 1, 0, -1, 1); +				_gnapActionStatus = kASEnterBarn; +				if (_cursorValue == 1) +					_newSceneNum = 6; +				else +					_newSceneNum = 36; +			} else if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemNeedle) { +					if (gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, +						getGnapSequenceId(gskIdle, _hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y) | 0x10000, 1)) +						_gnapActionStatus = kASPickPadlock; +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 7, 4); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(7, 4); +						break; +					case GRAB_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, +							0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASTryPickPadlock; +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSExitHouse: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, 0x107AF, 1); +				_gnapActionStatus = kASLeaveScene; +				if (isFlag(0)) +					platypusWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y + 1, -1, 0x107C7, 1); +				if (_cursorValue == 1) +					_newSceneNum = 4; +				else +					_newSceneNum = 37; +			} +			break; + +		case kHSWalkArea1: +		case kHSWalkArea2: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; +			 +		case kHSWalkArea3: +			// Nothing +			break; + +		default: +			if (_mouseClickState.left && _gnapActionStatus < 0) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +		 +		} +	 +		scene05_updateAnimations(); +	 +		if (!isSoundPlaying(0x1091C)) +			playSound(0x1091C, 1); +	 +		if (!_isLeavingScene) { +			if (isFlag(0)) +				updateBeaverIdleSequence(); +			updateGnapIdleSequence(); +			if (!_timers[5]) { +				_timers[5] = getRandom(20) + 30; +				if (_gnapActionStatus != kASTalkChicken && _s05_nextChickenSequenceId == -1) { +					if (getRandom(4) != 0) +						_s05_nextChickenSequenceId = 0x142; +					else +						_s05_nextChickenSequenceId = 0x143; +				} +			} +			if (!_timers[6]) { +				_timers[6] = getRandom(150) + 300; +				if (_gnapActionStatus < 0) +					_gameSys->insertSequence(0x149, 39, 0, 0, kSeqNone, 0, 0, 0); +			} +			playSoundC(); +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene05_updateHotspots(); +			_timers[5] = getRandom(20) + 30; +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene05_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASLeaveScene: +			_sceneDone = true; +			_gnapActionStatus = -1; +			break; +		case kASTryPickPadlock: +			_gameSys->insertSequence(0x148, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x148; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = -1; +			break; +		case kASPickPadlock: +			_gameSys->setAnimation(0x147, _gnapId, 0); +			_gameSys->insertSequence(0x147, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x147; +			_gnapSequenceDatNum = 0; +			setFlag(7); +			setFlag(11); +			setGrabCursorSprite(-1); +			_newSceneNum = 6; +			_timers[2] = 100; +			invRemove(kItemNeedle); +			_gnapActionStatus = kASLeaveScene; +			break; +		case kASTalkChicken: +			_s05_nextChickenSequenceId = 0x144; +			_gnapActionStatus = -1; +			break; +		case kASGrabChicken: +			_s05_nextChickenSequenceId = 0x14B; +			break; +		case kASGrabLadder: +			while (_gameSys->isSequenceActive(0x149, 39)) +				gameUpdateTick(); +			_gameSys->insertSequence(0x14E, _gnapId + 1, 0, 0, kSeqNone, 0, 0, 0); +			_gameSys->insertSequence(0x14D, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x14D; +			_gnapSequenceDatNum = 0; +			_timers[2] = 200; +			_timers[6] = 300; +			_gnapActionStatus = -1; +			break; +		case kASEnterBarn: +			_gameSys->insertSequence(0x107B1, 1, +				makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +				kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +			_gameSys->setAnimation(0x107B1, 1, 0); +			_gnapActionStatus = kASLeaveScene; +			break; +		case kASUseTwigWithChicken: +			playGnapShowItem(5, 0, 0); +			_s05_nextChickenSequenceId = 0x14F; +			_gnapActionStatus = -1; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(1) == 2) { +		if (_beaverSequenceId == 0x146) { +			_platX = 4; +			_platY = 8; +			_gameSys->insertSequence(0x107C1, 160, 0x146, 256, kSeqSyncWait, 0, 300 - _platGridX, 384 - _platGridY); +			_beaverSequenceId = 0x7C1; +			_beaverSequenceDatNum = 1; +			_beaverId = 20 * _platY; +			invAdd(kItemNeedle); +			setFlag(2); +			setGrabCursorSprite(kItemNeedle); +			showCursor(); +			_timers[1] = 30; +			_beaverActionStatus = -1; +		} +		if (_beaverActionStatus == kASPlatSearchHaystack) { +			_gameSys->setAnimation(0, 0, 1); +			_gameSys->insertSequence(0x145, _beaverId, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x146, 256, 0x145, _beaverId, kSeqSyncWait, 0, 0, 0); +			hideCursor(); +			setGrabCursorSprite(-1); +			_beaverSequenceId = 0x146; +			_beaverSequenceDatNum = 0; +			_gameSys->setAnimation(0x146, 256, 1); +			_timers[1] = 300; +		} +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2) { +		if (_s05_nextChickenSequenceId == 0x14B) { +			_gameSys->setAnimation(_s05_nextChickenSequenceId, 100, 3); +			_gameSys->insertSequence(_s05_nextChickenSequenceId, 100, _s05_currChickenSequenceId, 100, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x14C, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x14C; +			_s05_currChickenSequenceId = _s05_nextChickenSequenceId; +			_s05_nextChickenSequenceId = -1; +			_gnapActionStatus = -1; +		} else if (_s05_nextChickenSequenceId != -1) { +			_gameSys->setAnimation(_s05_nextChickenSequenceId, 100, 3); +			_gameSys->insertSequence(_s05_nextChickenSequenceId, 100, _s05_currChickenSequenceId, 100, kSeqSyncWait, 0, 0, 0); +			_s05_currChickenSequenceId = _s05_nextChickenSequenceId; +			_s05_nextChickenSequenceId = -1; +		} +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene06.cpp b/engines/gnap/scenes/scene06.cpp new file mode 100644 index 0000000000..3878d3514e --- /dev/null +++ b/engines/gnap/scenes/scene06.cpp @@ -0,0 +1,446 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus			= 0, +	kHSGas				= 1, +	kHSLadder			= 2, +	kHSHorse			= 3, +	kHSExitOutsideBarn	= 4, +	kHSDevice			= 5, +	kHSWalkArea1		= 6, +	kHSWalkArea2		= 7, +	kHSWalkArea3		= 8, +	kHSWalkArea4		= 9, +	kHSWalkArea5		= 10 +}; + +enum { +	kASTryToGetGas			= 0, +	kASTryToClimbLadder		= 1, +	kASTryToClimbLadderDone	= 2, +	kASTalkToHorse			= 3, +	kASUseTwigOnHorse		= 4, +	kASLeaveScene			= 5 +}; + +int GnapEngine::scene06_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	_gameSys->setAnimation(0, 0, 2); +	if (isFlag(11)) { +		playSound(0x11B, 0); +		clearFlag(11); +	} +	return 0x101; +} + +void GnapEngine::scene06_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSGas, 300, 120, 440, 232, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 4, 7); +	setHotspot(kHSLadder, 497, 222, 614, 492, SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 8); +	setHotspot(kHSHorse, 90, 226, 259, 376, SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 4, 7); +	setHotspot(kHSExitOutsideBarn, 226, 580, 688, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 10); +	setHotspot(kHSWalkArea1, 0, 0, 200, 515); +	setHotspot(kHSWalkArea2, 200, 0, 285, 499); +	setHotspot(kHSWalkArea3, 688, 0, 800, 499); +	setHotspot(kHSWalkArea4, 475, 469, 800, 505); +	setHotspot(kHSWalkArea5, 0, 0, 800, 504); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +    if (isFlag(29))  +    	_hotspots[kHSLadder].flags = SF_DISABLED; +	if (_cursorValue == 4) { +		_hotspots[kHSLadder].flags = SF_DISABLED; +		_hotspots[kHSGas].flags = SF_DISABLED; +	} +	_hotspotsCount = 11; +} + +void GnapEngine::scene06_run() { +	bool triedDeviceOnGas = false; +	 +	startSoundTimerC(7); + +	_s06_horseTurnedBack = false; +	_gameSys->insertSequence(0xF1, 120, 0, 0, kSeqNone, 0, 0, 0); + +	_s06_currHorseSequenceId = 0xF1; +	_s06_nextHorseSequenceId = -1; + +	_gameSys->setAnimation(0xF1, 120, 2); + +	_timers[4] = getRandom(40) + 25; + +	if (isFlag(4)) +		_gameSys->insertSequence(0xF7, 20, 0, 0, kSeqNone, 0, 0, 0); +	else +		_gameSys->insertSequence(0xF8, 20, 0, 0, kSeqNone, 0, 0, 0); +	 +	if (!isFlag(29) && _cursorValue != 4) +		_gameSys->insertSequence(0xFE, 20, 0, 0, kSeqNone, 0, 0, 0); +	 +	queueInsertDeviceIcon(); +	 +	initGnapPos(5, 12, 1); +	initBeaverPos(6, 12, 0); +	endSceneInit(); +	 +	platypusWalkTo(6, 8, -1, 0x107C2, 1); +	gnapWalkTo(5, 8, -1, 0x107B9, 1); +	 +	while (!_sceneDone) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +		 +		testWalk(0, 5, -1, -1, -1, -1); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene06_updateHotspots(); +			} +			break; +		 +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemDisguise) { +					gnapUseDisguiseOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						if (isFlag(5)) +							playGnapMoan1(_platX, _platY); +						else +							playGnapScratchingHead(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSGas: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 5, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(5, 0); +						break; +					case GRAB_CURSOR: +						if (isFlag(4)) { +							playGnapImpossible(0, 0); +						} else if (triedDeviceOnGas) { +							_hotspots[kHSWalkArea5].flags |= SF_WALKABLE; +							gnapWalkTo(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y, 0, 0x107BC, 1); +							_hotspots[kHSWalkArea5].flags &= ~SF_WALKABLE; +							_gnapActionStatus = kASTryToGetGas; +						} else { +							triedDeviceOnGas = true; +							playGnapPullOutDeviceNonWorking(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y); +						} +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						if (isFlag(4)) +							playGnapImpossible(0, 0); +						else +							playGnapScratchingHead(5, 0); +						break; +					} +				} +			} +			break; + +		case kHSLadder: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 8, 4); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(8, 4); +						break; +					case GRAB_CURSOR: +						if (isFlag(29)) +							playGnapImpossible(0, 0); +						else { +							gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, 0x107BB, 1); +							_gnapActionStatus = kASTryToClimbLadder; +							setFlag(29); +						} +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSHorse: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemTwig && _s06_horseTurnedBack) { +					_hotspots[kHSWalkArea5].flags |= SF_WALKABLE; +					gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, 0x107BC, 1); +					_hotspots[kHSWalkArea5].flags &= ~SF_WALKABLE; +					_gnapIdleFacing = 5; +					platypusWalkTo(6, 8, 1, 0x107C2, 1); +					_beaverFacing = 0; +					_gnapActionStatus = kASUseTwigOnHorse; +					setGrabCursorSprite(-1); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 3, 2); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(3, 2); +						break; +					case TALK_CURSOR: +						if (_s06_horseTurnedBack) { +							gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskBrainPulsating, 3, 2) | 0x10000, 1); +						} else { +							_gnapIdleFacing = 3; +							_hotspots[kHSWalkArea5].flags |= SF_WALKABLE; +							gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +							_hotspots[kHSWalkArea5].flags &= ~SF_WALKABLE; +							_gnapActionStatus = kASTalkToHorse; +						} +						break; +					case GRAB_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSExitOutsideBarn: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 0, 0x107AE, 1); +				_gnapActionStatus = kASLeaveScene; +				if (_cursorValue == 1) +					_newSceneNum = 5; +				else +					_newSceneNum = 35; +			} +			break; + +		case kHSWalkArea1: +		case kHSWalkArea2: +		case kHSWalkArea3: +		case kHSWalkArea4: +		case kHSWalkArea5: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; + +		default: +			if (_mouseClickState.left && _gnapActionStatus < 0) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; + +		} +	 +	 +		scene06_updateAnimations(); +	 +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0) +				updateBeaverIdleSequence(); +			if (_gnapActionStatus < 0) +				updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = getRandom(40) + 25; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s06_nextHorseSequenceId == -1) { +					if (_s06_horseTurnedBack) { +						_s06_nextHorseSequenceId = 0xF5; +					} else { +						switch (getRandom(5)) { +						case 0: +						case 1: +						case 2: +							_s06_nextHorseSequenceId = 0xF1; +							break; +						case 3: +							_s06_nextHorseSequenceId = 0xF3; +							break; +						case 4: +							_s06_nextHorseSequenceId = 0xF4; +							break; +						} +					} +				} +			} +			playSoundC(); +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene06_updateHotspots(); +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene06_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASLeaveScene: +			_sceneDone = true; +			_gnapActionStatus = -1; +			break; +		case kASTryToGetGas: +			_gameSys->insertSequence(0xFC, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0xFC; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = -1; +			break; +		case kASTryToClimbLadder: +			_gameSys->insertSequence(0xFF, 20, 0xFE, 20, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(0xFD, _gnapId, 0); +			_gameSys->insertSequence(0xFD, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0xFD; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = kASTryToClimbLadderDone; +			break; +		case kASTryToClimbLadderDone: +			_gnapX = 6; +			_gnapY = 7; +			_gnapActionStatus = -1; +			break; +		case kASTalkToHorse: +			_s06_nextHorseSequenceId = 0xF6; +			break; +		case kASUseTwigOnHorse: +			_s06_nextPlatSequenceId = 0xFB; +			break; +		default: +			_gnapActionStatus = -1; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(1) == 2) { +		_gameSys->setAnimation(0, 0, 1); +		if (_beaverSequenceId == 0xFA) { +			_gameSys->setAnimation(0, 0, 1); +			invAdd(kItemGas); +			setFlag(29); +			_hotspots[kHSLadder].flags = SF_DISABLED; +			setGrabCursorSprite(kItemGas); +			_beaverActionStatus = -1; +			_platX = 6; +			_platY = 8; +			_gameSys->insertSequence(0x107C1, _beaverId, 0, 0, kSeqNone, 0, 450 - _platGridX, 384 - _platGridY); +			_beaverSequenceId = 0x7C1; +			_beaverSequenceDatNum = 1; +			setFlag(4); +			_gnapActionStatus = -1; +			showCursor(); +		} +		if (_s06_nextPlatSequenceId == 0xFB) { +			_gameSys->setAnimation(0, 0, 1); +			_s06_nextHorseSequenceId = 0xF2; +			_beaverActionStatus = 6; +		} +	} +	 +	if (_gameSys->getAnimationStatus(2) == 2 && _s06_nextHorseSequenceId != -1) { +		switch (_s06_nextHorseSequenceId) { +		case 0xF2: +			setGrabCursorSprite(-1); +			hideCursor(); +			_gameSys->setAnimation(0xFA, 256, 1); +			_gameSys->insertSequence(0xF2, 120, _s06_currHorseSequenceId, 120, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x100, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0xF7, 20, 0xF8, 20, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0xFB, _beaverId, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0xFA, 256, 0xFB, _beaverId, kSeqSyncWait, 0, 0, 0); +			_beaverSequenceId = 0xFA; +			_beaverSequenceDatNum = 0; +			_gameSys->insertSequence(0x107B7, _gnapId, 0x100, _gnapId, +				kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +			_gnapSequenceId = 0x7B7; +			_gnapSequenceDatNum = 1; +			_s06_currHorseSequenceId = _s06_nextHorseSequenceId; +			_s06_nextHorseSequenceId = -1; +			_s06_nextPlatSequenceId = -1; +			invRemove(kItemTwig); +			break; +		case 0xF6: +			_gameSys->setAnimation(_s06_nextHorseSequenceId, 120, 2); +			_gameSys->insertSequence(0xF6, 120, _s06_currHorseSequenceId, 120, kSeqSyncWait, 0, 0, 0); +			_s06_horseTurnedBack = true; +			_s06_currHorseSequenceId = _s06_nextHorseSequenceId; +			_s06_nextHorseSequenceId = -1; +			_gnapActionStatus = -1; +			break; +		default: +			_gameSys->setAnimation(_s06_nextHorseSequenceId, 120, 2); +			_gameSys->insertSequence(_s06_nextHorseSequenceId, 120, _s06_currHorseSequenceId, 120, kSeqSyncWait, 0, 0, 0); +			_s06_currHorseSequenceId = _s06_nextHorseSequenceId; +			_s06_nextHorseSequenceId = -1; +			break; +		} +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene07.cpp b/engines/gnap/scenes/scene07.cpp new file mode 100644 index 0000000000..9b8ee2975b --- /dev/null +++ b/engines/gnap/scenes/scene07.cpp @@ -0,0 +1,275 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSExitHouse	= 1, +	kHSDice			= 2, +	kHSDevice		= 3, +	kHSWalkArea1	= 4, +	kHSWalkArea2	= 5, +	kHSWalkArea3	= 6 +}; + +enum { +	kASWait			= 0, +	kASLeaveScene	= 1 +}; + +int GnapEngine::scene07_init() { +	return 0x92; +} + +void GnapEngine::scene07_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitHouse, 700, 125, 799, 290, SF_EXIT_NE_CURSOR); +	setHotspot(kHSDice, 200, 290, 270, 360, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSWalkArea1, 0, 0, 325, 445); +	setHotspot(kHSWalkArea2, 325, 0, 799, 445, _isLeavingScene ? SF_WALKABLE : 0); +	setHotspot(kHSWalkArea3, 160, 0, 325, 495); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	if (isFlag(0)) +		_hotspots[kHSDice].flags = SF_DISABLED; +	_hotspotsCount = 7; +} + +void GnapEngine::scene07_run() { +	 +	queueInsertDeviceIcon(); +	_gameSys->insertSequence(0x8C, 1, 0, 0, kSeqLoop, 0, 0, 0); +	_gameSys->insertSequence(0x90, 1, 0, 0, kSeqLoop, 0, 0, 0); + +	invRemove(kItemGas); +	invRemove(kItemNeedle); +	 +	if (!isFlag(0)) +		_gameSys->insertSequence(0x8D, 1, 0, 0, kSeqNone, 0, 0, 0); + +	if (_prevSceneNum == 8) { +		initGnapPos(7, 7, 3); +		initBeaverPos(9, 7, 4); +		endSceneInit(); +	} else { +		_gnapX = 6; +		_gnapY = 7; +		_gnapId = 140; +		_gnapSequenceId = 0x8F; +		_gnapSequenceDatNum = 0; +		_gnapIdleFacing = 1; +		_gameSys->insertSequence(0x8F, 140, 0, 0, kSeqNone, 0, 0, 0); +		_gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0); +		_gnapActionStatus = kASWait; +		_platX = 3; +		_platY = 8; +		_beaverId = 160; +		_beaverSequenceId = 0x91; +		_beaverSequenceDatNum = 0; +		_beaverFacing = 0; +		_gameSys->insertSequence(0x91, 160, 0, 0, kSeqNone, 0, 0, 0); +		endSceneInit(); +	} + +	_timers[3] = 600; +	_timers[4] = getRandom(40) + 50; + +	while (!_sceneDone) { + +		if (!isSoundPlaying(0x10919)) +			playSound(0x10919, 1); + +		if (testWalk(0, 1, 8, 7, 6, 7)) +			scene07_updateHotspots(); + +		updateMouseCursor(); +		updateCursorByHotspot(); + +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); + +		switch (_sceneClickedHotspot) { + +		case kHSPlatypus: +			switch (_verbCursor) { +			case LOOK_CURSOR: +				playGnapMoan1(_platX, _platY); +				break; +			case GRAB_CURSOR: +				gnapKissPlatypus(0); +				break; +			case TALK_CURSOR: +				playGnapBrainPulsating(_platX, _platY); +				playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +				break; +			case PLAT_CURSOR: +				break; +			} +			break; + +		case kHSExitHouse: +			_isLeavingScene = true; +			if (_gnapX > 8) +				gnapWalkTo(_gnapX, 7, 0, 0x107AD, 1); +			else +				gnapWalkTo(8, 7, 0, 0x107AD, 1); +			_gnapActionStatus = kASLeaveScene; +			break; + +		case kHSDice: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapShowCurrItem(4, 8, 3, 3); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					break; +				case GRAB_CURSOR: +					setFlag(0); +					invAdd(kItemDice); +					scene07_updateHotspots(); +					playGnapPullOutDevice(3, 3); +					_gameSys->setAnimation(0x8E, 1, 2); +					_gameSys->insertSequence(0x8E, 1, 141, 1, kSeqSyncWait, 0, 0, 0); +					_gameSys->insertSequence(getGnapSequenceId(gskUseDevice, 0, 0) | 0x10000, _gnapId, +						makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +						kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +					_gnapSequenceId = getGnapSequenceId(gskUseDevice, 0, 0); +					_gnapSequenceDatNum = 1; +					break; +				case TALK_CURSOR: +				case PLAT_CURSOR: +					playGnapImpossible(0, 0); +					break; +				} +			} +			break; + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene07_updateHotspots(); +				_timers[4] = getRandom(40) + 50; +			} +			break; + +		case kHSWalkArea1: +		case kHSWalkArea2: +			gnapWalkTo(-1, -1, -1, -1, 1); +			break; +			 +		case kHSWalkArea3: +			// Nothing +			break; + +		default: +			if (_mouseClickState.left) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +			 +		} + +		scene07_updateAnimations(); + +		if (!_isLeavingScene) { +			updateGnapIdleSequence(); +			if (_beaverActionStatus < 0 && _gnapActionStatus < 0) { +				if (_timers[0]) { +					if (!_timers[1]) { +						_timers[1] = getRandom(20) + 30; +						_gnapRandomValue = getRandom(20); +						// TODO Cleanup +						if (_beaverFacing != 0) { +							if (_gnapRandomValue != 0 || _beaverSequenceId != 0x7CA) { +								if (_gnapRandomValue != 1 || _beaverSequenceId != 0x7CA) { +									if (_platY == 9) +										playBeaverSequence(0x107CA); +								} else { +									playBeaverSequence(0x10845); +								} +							} else { +								playBeaverSequence(0x107CC); +							} +						} else if (_gnapRandomValue != 0 || _beaverSequenceId != 0x7C9) { +							if (_gnapRandomValue != 1 || _beaverSequenceId != 0x7C9) { +								if (_platY == 9) +									playBeaverSequence(0x107C9); +							} else { +								playBeaverSequence(0x10844); +							} +						} else { +							playBeaverSequence(0x107CB); +						} +						_gameSys->setAnimation(_beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, 1); +					} +				} else { +					_timers[0] = getRandom(75) + 75; +					beaverMakeRoom(); +				} +			} else { +				_timers[0] = 100; +				_timers[1] = 35; +			} +			sceneXX_playRandomSound(4); +		} + +		checkGameKeys(); + +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene07_updateHotspots(); +			_timers[4] = getRandom(40) + 50; +		} +		 +		gameUpdateTick(); +		 +	} + +} + +void GnapEngine::scene07_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASLeaveScene: +			_newSceneNum = 8; +			_sceneDone = true; +			break; +		} +		_gnapActionStatus = -1; +	} + +	if (_gameSys->getAnimationStatus(2) == 2) { +		_gameSys->setAnimation(0, 0, 2); +		setGrabCursorSprite(kItemDice); +	} +	 +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene08.cpp b/engines/gnap/scenes/scene08.cpp new file mode 100644 index 0000000000..a4ebf92c71 --- /dev/null +++ b/engines/gnap/scenes/scene08.cpp @@ -0,0 +1,527 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSExitBackdoor	= 1, +	kHSExitCrash	= 2, +	kHSMan			= 3, +	kHSDoor			= 4, +	kHSMeat			= 5, +	kHSBone			= 6, +	kHSToy			= 7, +	kHSWalkArea1	= 8, +	kHSDevice		= 9, +	kHSWalkArea2	= 10 +}; + +enum { +	kASLeaveScene		= 0, +	kASTalkMan			= 1, +	kASLookMan			= 2, +	kASLookDog			= 3, +	kASGrabDog			= 4, +	kASTalkDog			= 5, +	kASPlatWithMan		= 6, +	kASPlatWithDog		= 7 +}; + +int GnapEngine::scene08_init() { +	return 0x150; +} + +void GnapEngine::scene08_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitBackdoor, 0, 280, 10, 400, SF_EXIT_L_CURSOR | SF_WALKABLE); +	setHotspot(kHSExitCrash, 200, 590, 400, 599, SF_EXIT_D_CURSOR | SF_WALKABLE); +	setHotspot(kHSMan, 510, 150, 610, 380, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSDoor, 350, 170, 500, 410, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSMeat, 405, 450, 480, 485, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSBone, 200, 405, 270, 465, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSToy, 540, 430, 615, 465, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSWalkArea1, 290, 340, -1, -1); +	setHotspot(kHSWalkArea2, 0, 0, 799, 420); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	if (isFlag(7)) +		_hotspots[kHSMeat].flags = SF_WALKABLE | SF_DISABLED; +	if (isFlag(8)) +		_hotspots[kHSBone].flags = SF_WALKABLE | SF_DISABLED; +	if (isFlag(9)) +		_hotspots[kHSToy].flags = SF_WALKABLE | SF_DISABLED; +	_hotspotsCount = 11; +} + +void GnapEngine::scene08_updateAnimationsCb() { +	if (_gameSys->getAnimationStatus(3) == 2) { +		_gameSys->setAnimation(_s08_nextDogSequenceId, 100, 3); +		_gameSys->insertSequence(_s08_nextDogSequenceId, 100, _s08_currDogSequenceId, 100, kSeqSyncWait, 0, 0, 0); +		_s08_currDogSequenceId = _s08_nextDogSequenceId; +		if ( _s08_nextDogSequenceId != 0x135 ) +			_s08_nextDogSequenceId = 0x134; +	} +} + +void GnapEngine::scene08_run() { +	 +	queueInsertDeviceIcon(); + +	_gameSys->insertSequence(0x14F, 1, 0, 0, kSeqLoop, 0, 0, 0); +	_gameSys->insertSequence(0x14E, 256, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s08_currDogSequenceId = 0x135; +	_s08_nextDogSequenceId = 0x135; +	 +	_gameSys->setAnimation(0x135, 100, 3); +	_gameSys->insertSequence(_s08_currDogSequenceId, 100, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s08_currManSequenceId = 0x140; +	_s08_nextManSequenceId = -1; +	 +	_gameSys->setAnimation(0x140, 100, 2); +	_gameSys->insertSequence(_s08_currManSequenceId, 100, 0, 0, kSeqNone, 0, 0, 0); +	 +	_timers[4] = getRandom(50) + 75; +	 +	if (!isFlag(7)) +		_gameSys->insertSequence(0x144, 1, 0, 0, kSeqNone, 0, 0, 0); +	 +	if (!isFlag(8)) +		_gameSys->insertSequence(0x145, 1, 0, 0, kSeqNone, 0, 0, 0); +	 +	if (!isFlag(9)) +		_gameSys->insertSequence(0x146, 1, 0, 0, kSeqNone, 0, 0, 0); +	 +	initGnapPos(-1, 8, 1); +	initBeaverPos(-1, 7, 0); +	 +	endSceneInit(); +	 +	gnapWalkTo(1, 8, -1, 0x107B9, 1); +	platypusWalkTo(1, 7, -1, 0x107C2, 1); +	 +	_timers[5] = getRandom(40) + 50; +	 +	while (!_sceneDone) { +	 +		if (!isSoundPlaying(0x10919)) +			playSound(0x10919, 1); +	 +		testWalk(0, 0, -1, -1, -1, -1); +		 +		updateMouseCursor(); +		updateCursorByHotspot(); + +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene08_updateHotspots(); +				_timers[4] = getRandom(50) + 75; +				_timers[5] = getRandom(40) + 50; +			} +			break; + +		case kHSPlatypus: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapImpossible(0, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					if (isFlag(11)) +						playGnapMoan1(_platX, _platY); +					else +						playGnapScratchingHead(_platX, _platY); +					break; +				case GRAB_CURSOR: +					gnapActionIdle(0x14D); +					gnapKissPlatypus(8); +					break; +				case TALK_CURSOR: +					playGnapBrainPulsating(_platX, _platY); +					playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +					break; +				case PLAT_CURSOR: +					break; +				} +			} +			break; + +		case kHSExitBackdoor: +			_isLeavingScene = 1; +			gnapActionIdle(0x14D); +			gnapWalkTo(0, 6, 0, 0x107AF, 1); +			_gnapActionStatus = kASLeaveScene; +			platypusWalkTo(0, 7, 1, 0x107CF, 1); +			_newSceneNum = 9; +			break; + +		case kHSExitCrash: +			_isLeavingScene = 1; +			gnapActionIdle(0x14D); +			gnapWalkTo(3, 9, 0, 0x107AE, 1); +			_gnapActionStatus = kASLeaveScene; +			platypusWalkTo(4, 9, 1, 0x107C1, 1); +			_newSceneNum = 7; +			break; + +		case kHSMan: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapShowCurrItem(6, 6, 7, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					gnapActionIdle(0x14D); +					gnapWalkTo(6, 6, 0, 0x107BB, 1); +					_gnapActionStatus = kASLookMan; +					_gnapIdleFacing = 7; +					break; +				case GRAB_CURSOR: +					playGnapImpossible(0, 0); +					break; +				case TALK_CURSOR: +					_gnapIdleFacing = 5; +					gnapActionIdle(0x14D); +					gnapWalkTo(8, 6, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +					_gnapActionStatus = kASTalkMan; +					break; +				case PLAT_CURSOR: +					gnapActionIdle(0x14D); +					gnapUseDeviceOnBeaver(); +					platypusWalkTo(6, 6, 1, 0x107C2, 1); +					_beaverActionStatus = kASPlatWithMan; +					_beaverFacing = 0; +					playGnapIdle(6, 6); +					break; +				} +			} +			break; + +		case kHSDoor: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapShowCurrItem(4, 7, 5, 0); +				_gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0); +				_gnapActionStatus = kASGrabDog; +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playGnapScratchingHead(6, 0); +					_gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0); +					_gnapActionStatus = kASLookDog; +					break; +				case GRAB_CURSOR: +					gnapWalkTo(4, 7, 0, 0x107BB, 1); +					_gnapActionStatus = kASGrabDog; +					_gnapIdleFacing = 7; +					break; +				case TALK_CURSOR: +					_gnapIdleFacing = 7; +					gnapActionIdle(0x14D); +					gnapWalkTo(4, 7, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +					_gnapActionStatus = kASTalkDog; +					break; +				case PLAT_CURSOR: +					setFlag(11); +					gnapActionIdle(0x14D); +					gnapUseDeviceOnBeaver(); +					platypusWalkTo(3, 7, 1, 0x107C2, 1); +					_beaverActionStatus = kASPlatWithDog; +					_beaverFacing = 0; +					playGnapIdle(3, 7); +					break; +				} +			} +			break; + +		case kHSMeat: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapShowCurrItem(6, 8, 5, 6); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playGnapScratchingHead(6, 7); +					break; +				case GRAB_CURSOR: +					if (_s08_currDogSequenceId == 0x135) { +						playGnapScratchingHead(6, 7); +					} else { +						gnapActionIdle(0x14D); +						playGnapPullOutDevice(6, 7); +						playGnapUseDevice(0, 0); +						_s08_nextDogSequenceId = 0x149; +					} +					break; +				case TALK_CURSOR: +				case PLAT_CURSOR: +					playGnapImpossible(0, 0); +					break; +				} +			} +			break; + +		case kHSBone: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapShowCurrItem(2, 7, 3, 6); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playGnapScratchingHead(3, 6); +					break; +				case GRAB_CURSOR: +					if (_s08_currDogSequenceId == 0x135) { +						playGnapScratchingHead(3, 6); +					} else { +						gnapActionIdle(0x14D); +						playGnapPullOutDevice(3, 6); +						playGnapUseDevice(0, 0); +						_s08_nextDogSequenceId = 0x14A; +					} +					break; +				case TALK_CURSOR: +				case PLAT_CURSOR: +					playGnapImpossible(0, 0); +					break; +				} +			} +			break; + +		case kHSToy: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapShowCurrItem(8, 7, 7, 6); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playGnapScratchingHead(7, 6); +					break; +				case GRAB_CURSOR: +					if (_s08_currDogSequenceId == 0x135) { +						playGnapScratchingHead(7, 6); +					} else { +						gnapActionIdle(0x14D); +						playGnapPullOutDevice(7, 6); +						playGnapUseDevice(0, 0); +						_s08_nextDogSequenceId = 0x14B; +					} +					break; +				case TALK_CURSOR: +				case PLAT_CURSOR: +					playGnapImpossible(0, 0); +					break; +				} +			} +			break; + +		case kHSWalkArea1: +		case kHSWalkArea2: +			gnapActionIdle(0x14D); +			gnapWalkTo(-1, 6, -1, -1, 1); +			break; + +		default: +			if (_mouseClickState.left) { +				gnapActionIdle(0x14D); +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; + +		} +	 +		scene08_updateAnimations(); +	 +		if (!_isLeavingScene) { +			updateBeaverIdleSequence(); +			updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = getRandom(50) + 125; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s08_nextManSequenceId == -1 && +					(_s08_currDogSequenceId == 0x134 || _s08_currDogSequenceId == 0x135)) { +					_gnapRandomValue = getRandom(4); +					switch (_gnapRandomValue) { +					case 0: +						_s08_nextManSequenceId = 0x138; +						break; +					case 1: +						_s08_nextManSequenceId = 0x136; +						break; +					case 2: +						_s08_nextManSequenceId = 0x13B; +						break; +					case 3: +						_s08_nextManSequenceId = 0x13A; +						break; +					} +				} +			} +			sceneXX_playRandomSound(5); +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene08_updateHotspots(); +			_timers[4] = getRandom(50) + 75; +			_timers[5] = getRandom(40) + 50; +		} +		 +		gameUpdateTick(); +	 +	} +	 +} + +void GnapEngine::scene08_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASLeaveScene: +			_sceneDone = true; +			_gnapActionStatus = -1; +			break; +		case kASTalkMan: +			_s08_nextManSequenceId = 0x13F; +			_gnapActionStatus = -1; +			break; +		case kASLookMan: +			_s08_nextManSequenceId = 0x140; +			_gnapActionStatus = -1; +			break; +		case kASLookDog: +			_s08_nextManSequenceId = 0x137; +			_gnapActionStatus = -1; +			break; +		case kASGrabDog: +			if (_s08_currDogSequenceId == 0x135) +				_s08_nextDogSequenceId = 0x133; +			else +				_s08_nextDogSequenceId = 0x13C; +			_gnapActionStatus = -1; +			break; +		case kASTalkDog: +			if (_s08_currDogSequenceId == 0x135) +				_s08_nextDogSequenceId = 0x133; +			else +				_s08_nextDogSequenceId = 0x13C; +			_gnapActionStatus = -1; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(1) == 2) { +		_gameSys->setAnimation(0, 0, 1); +		switch (_beaverActionStatus) { +		case kASPlatWithDog: +			_s08_nextDogSequenceId = 0x147; +			break; +		case kASPlatWithMan: +			_s08_nextManSequenceId = 0x140; +			_beaverActionStatus = -1; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(2) == 2 && _s08_nextManSequenceId != -1) { +		_gameSys->setAnimation(_s08_nextManSequenceId, 100, 2); +		_gameSys->insertSequence(_s08_nextManSequenceId, 100, _s08_currManSequenceId, 100, kSeqSyncWait, 0, 0, 0); +		_s08_currManSequenceId = _s08_nextManSequenceId; +		_s08_nextManSequenceId = -1; +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2) { +		if (_s08_currDogSequenceId == 0x147) +			_beaverActionStatus = -1; +		if (_s08_currDogSequenceId == 0x149 || _s08_currDogSequenceId == 0x14A || _s08_currDogSequenceId == 0x14B) { +			if (getRandom(2) != 0) +				_s08_nextManSequenceId = 0x13D; +			else +				_s08_nextManSequenceId = 0x13E; +		} else if (_s08_currDogSequenceId == 0x133) +			_s08_nextManSequenceId = 0x139; +		if (_s08_nextDogSequenceId == 0x149 || _s08_nextDogSequenceId == 0x14A || _s08_nextDogSequenceId == 0x14B) { +			_gameSys->setAnimation(_s08_nextDogSequenceId, 100, 3); +			_gameSys->insertSequence(_s08_nextDogSequenceId, 100, _s08_currDogSequenceId, 100, kSeqSyncWait, 0, 0, 0); +			switch (_s08_nextDogSequenceId) { +			case 0x149: +				setFlag(7); +				_hotspots[kHSMeat].flags = SF_DISABLED | SF_WALKABLE; +				_gameSys->removeSequence(0x144, 1, 1); +				break; +			case 0x14A: +				setFlag(8); +				_hotspots[kHSBone].flags = SF_DISABLED | SF_WALKABLE; +				_gameSys->removeSequence(0x145, 1, 1); +				break; +			case 0x14B: +				setFlag(9); +				_hotspots[kHSToy].flags = SF_DISABLED | SF_WALKABLE; +				_gameSys->removeSequence(0x146, 1, 1); +				break; +			} +			_s08_currDogSequenceId = _s08_nextDogSequenceId; +			_s08_nextDogSequenceId = 0x134; +		} else if (_s08_nextDogSequenceId == 0x147) { +			_gameSys->setAnimation(_s08_nextDogSequenceId, 100, 3); +			_gameSys->insertSequence(_s08_nextDogSequenceId, 100, _s08_currDogSequenceId, 100, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x148, 160, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0); +			_s08_currDogSequenceId = _s08_nextDogSequenceId; +			_s08_nextDogSequenceId = 0x134; +			_platX = 1; +			_platY = 8; +			_beaverId = 160; +			_beaverSequenceId = 0x148; +			_beaverFacing = 4; +			_beaverSequenceDatNum = 0; +			if (_gnapX == 1 && _gnapY == 8) +				gnapWalkStep(); +		} else if (_s08_nextDogSequenceId != -1) { +			_gameSys->setAnimation(_s08_nextDogSequenceId, 100, 3); +			_gameSys->insertSequence(_s08_nextDogSequenceId, 100, _s08_currDogSequenceId, 100, kSeqSyncWait, 0, 0, 0); +			_s08_currDogSequenceId = _s08_nextDogSequenceId; +			if (_s08_nextDogSequenceId != 0x135) +				_s08_nextDogSequenceId = 0x134; +			if (_s08_currDogSequenceId == 0x133) { +				_timers[2] = getRandom(30) + 20; +				_timers[3] = getRandom(50) + 200; +				_gameSys->insertSequence(0x14D, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +				_gnapSequenceId = 0x14D; +				_gnapIdleFacing = 7; +				_gnapSequenceDatNum = 0; +				_gnapActionStatus = -1; +			} +		} +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene09.cpp b/engines/gnap/scenes/scene09.cpp new file mode 100644 index 0000000000..4436d1e436 --- /dev/null +++ b/engines/gnap/scenes/scene09.cpp @@ -0,0 +1,241 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSExitKitchen	= 1, +	kHSExitHouse	= 2, +	kHSTrash		= 3, +	kHSDevice		= 4, +	kHSWalkArea1	= 5, +	kHSWalkArea2	= 6, +	kHSWalkArea3	= 7 +}; + +enum { +	kASLeaveScene		= 0, +	kASSearchTrash		= 1, +	kASSearchTrashDone	= 2 +}; + +int GnapEngine::scene09_init() { +	return 0x4E; +} + +void GnapEngine::scene09_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 200, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitKitchen, 280, 200, 380, 400, SF_EXIT_U_CURSOR); +	setHotspot(kHSExitHouse, 790, 200, 799, 450, SF_EXIT_R_CURSOR | SF_WALKABLE); +	setHotspot(kHSTrash, 440, 310, 680, 420, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSWalkArea1, 0, 0, 799, 400); +	setHotspot(kHSWalkArea2, 0, 0, 630, 450); +	setHotspot(kHSWalkArea2, 0, 0, 175, 495); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 8; +} + +void GnapEngine::scene09_run() { +	 +	queueInsertDeviceIcon(); +	 +	_gameSys->insertSequence(0x4D, 1, 0, 0, kSeqLoop, 0, 0, 0); +	_gameSys->insertSequence(0x4B, 2, 0, 0, kSeqNone, 0, 0, 0); +	 +	if (_prevSceneNum == 8) { +		initGnapPos(11, 8, 3); +		initBeaverPos(12, 7, 4); +		endSceneInit(); +		gnapWalkTo(9, 8, -1, 0x107BA, 1); +		platypusWalkTo(9, 7, -1, 0x107D2, 1); +	} else { +		initGnapPos(4, 7, 1); +		initBeaverPos(5, 7, 0); +		endSceneInit(); +	} + +	_timers[4] = getRandom(150) + 50; +	_timers[5] = getRandom(40) + 50; + +	while (!_sceneDone) { +	 +		if (!isSoundPlaying(0x10919)) +			playSound(0x10919, 1); +	 +		testWalk(0, 0, -1, -1, -1, -1); +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene09_updateHotspots(); +				_timers[4] = getRandom(150) + 50; +				_timers[5] = getRandom(40) + 50; +			} +			break; + +		case kHSPlatypus: +			switch (_verbCursor) { +			case LOOK_CURSOR: +				playGnapMoan1(_platX, _platY); +				break; +			case GRAB_CURSOR: +				gnapKissPlatypus(0); +				break; +			case TALK_CURSOR: +				playGnapBrainPulsating(_platX, _platY); +				playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +				break; +			case PLAT_CURSOR: +				break; +			} +			break; + +		case kHSExitKitchen: +			_isLeavingScene = 1; +			_newSceneNum = 10; +			gnapWalkTo(4, 7, 0, 0x107BF, 1); +			_gnapActionStatus = kASLeaveScene; +			platypusWalkTo(4, 8, -1, 0x107D2, 1); +			_beaverFacing = 4; +			break; + +		case kHSExitHouse: +			_isLeavingScene = 1; +			_newSceneNum = 8; +			gnapWalkTo(10, -1, 0, 0x107AB, 1); +			_gnapActionStatus = kASLeaveScene; +			platypusWalkTo(10, -1, -1, 0x107CD, 1); +			_beaverFacing = 4; +			break; + +		case kHSTrash: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapShowCurrItem(9, 6, 8, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playGnapScratchingHead(8, 3); +					break; +				case GRAB_CURSOR: +					_gnapActionStatus = kASSearchTrash; +					gnapWalkTo(9, 6, 0, 0x107BC, 1); +					break; +				case TALK_CURSOR: +				case PLAT_CURSOR: +					playGnapImpossible(0, 0); +					break; +				} +			} +			break; + +		case kHSWalkArea1: +		case kHSWalkArea2: +		case kHSWalkArea3: +			gnapWalkTo(-1, -1, -1, -1, 1); +			break; + +		default: +			if (_mouseClickState.left) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; + +		} +	 +		scene09_updateAnimations(); +	 +		if (!_isLeavingScene && _gnapActionStatus != 1 && _gnapActionStatus != 2) { +			updateBeaverIdleSequence(); +			updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = getRandom(150) + 100; +				if (_timers[4] & 1) +					_gameSys->insertSequence(0x49, 1, 0, 0, kSeqNone, 0, 0, 0); +				else +					_gameSys->insertSequence(0x4A, 1, 0, 0, kSeqNone, 0, 0, 0); +			} +			sceneXX_playRandomSound(5); +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene09_updateHotspots(); +			_timers[4] = getRandom(150) + 50; +			_timers[5] = getRandom(40) + 50; +		} +		 +		gameUpdateTick(); +		 +	} +   +} + +void GnapEngine::scene09_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASLeaveScene: +			_sceneDone = true; +			_gnapActionStatus = -1; +			break; +		case kASSearchTrash: +			_gameSys->setAnimation(0x4C, 120, 0); +			_gameSys->insertSequence(0x4C, 120, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->removeSequence(0x4B, 2, 1); +			_gnapSequenceId = 0x4C; +			_gnapId = 120; +			_gnapIdleFacing = 5; +			_gnapSequenceDatNum = 0; +			_gnapX = 9; +			_gnapY = 6; +			_gnapActionStatus = kASSearchTrashDone; +			break; +		case kASSearchTrashDone: +			_gameSys->insertSequence(0x4B, 2, 0, 0, kSeqNone, 0, 0, 0); +			_timers[2] = 360; +			_timers[4] = getRandom(150) + 100; +			_gnapActionStatus = -1; +			break; +		} +	} +   +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene10.cpp b/engines/gnap/scenes/scene10.cpp new file mode 100644 index 0000000000..c6faf5a0ca --- /dev/null +++ b/engines/gnap/scenes/scene10.cpp @@ -0,0 +1,500 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSExitBar		= 1, +	kHSExitBackdoor	= 2, +	kHSCook			= 3, +	kHSTongs		= 4, +	kHSBox			= 5, +	kHSOven			= 6, +	kHSWalkArea1	= 7, +	kHSDevice		= 8, +	kHSWalkArea2	= 9, +	kHSWalkArea3	= 10, +	kHSWalkArea4	= 11 +}; + +enum { +	kASLeaveScene		= 0, +	kASAnnoyCook		= 1, +	kASPlatWithBox		= 4 +}; + +int GnapEngine::scene10_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	_gameSys->setAnimation(0, 0, 2); +	return 0x10F; +} + +void GnapEngine::scene10_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitBar, 0, 75, 85, 455, SF_EXIT_NW_CURSOR); +	setHotspot(kHSExitBackdoor, 75, 590, 500, 599, SF_EXIT_D_CURSOR | SF_WALKABLE); +	setHotspot(kHSCook, 370, 205, 495, 460, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSTongs, 250, 290, 350, 337, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSBox, 510, 275, 565, 330, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSOven, 690, 280, 799, 420, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSWalkArea1, 59, 0, 495, 460); +	setHotspot(kHSWalkArea2, 495, 0, 650, 420); +	setHotspot(kHSWalkArea3, 651, 0, 725, 400); +	setHotspot(kHSWalkArea4, 725, 0, 799, 441); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 12; +} + +void GnapEngine::scene10_run() { + +	_s10_currCookSequenceId = 0x103; +	 +	_gameSys->setAnimation(0x103, 100, 2); +	_gameSys->insertSequence(0x103, 100, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s10_nextCookSequenceId = 0x106; +	if (!isFlag(1)) +		_gameSys->insertSequence(0x107, 100, 0, 0, kSeqNone, 0, 0, 0); +	 +	queueInsertDeviceIcon(); +	 +	if (_prevSceneNum == 9) { +		initGnapPos(11, 8, 3); +		initBeaverPos(12, 7, 4); +		endSceneInit(); +		gnapWalkTo(9, 8, -1, 0x107BA, 1); +		platypusWalkTo(9, 7, -1, 0x107D2, 1); +	} else { +		initGnapPos(-1, 7, 1); +		initBeaverPos(-2, 8, 0); +		endSceneInit(); +		gnapWalkTo(1, 7, -1, 0x107B9, 1); +		platypusWalkTo(1, 8, -1, 0x107C2, 1); +	} + +	_timers[4] = getRandom(80) + 150; +	_timers[5] = getRandom(100) + 100; + +	while (!_sceneDone) { +	 +		if (!isSoundPlaying(0x1091E)) +			playSound(0x1091E, 1); +	 +		if (!isSoundPlaying(0x1091A)) +			playSound(0x1091A, 1); +	 +		updateMouseCursor(); +	 +		testWalk(0, 0, -1, -1, -1, -1); +	 +		updateCursorByHotspot(); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSPlatypus: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapImpossible(0, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					if (isFlag(1)) +						playGnapMoan1(_platX, _platY); +					else +						playGnapScratchingHead(_platX, _platY); +					break; +				case GRAB_CURSOR: +					gnapKissPlatypus(10); +					break; +				case TALK_CURSOR: +					playGnapBrainPulsating(_platX, _platY); +					playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +					break; +				case PLAT_CURSOR: +					break; +				} +			} +			break; + +		case kHSExitBar: +			_isLeavingScene = 1; +			gnapActionIdle(0x10C); +			gnapWalkTo(0, 7, 0, 0x107AF, 1); +			_gnapActionStatus = kASLeaveScene; +			platypusWalkTo(0, 7, -1, 0x107CF, 1); +			_newSceneNum = 11; +			break; + +		case kHSExitBackdoor: +			_isLeavingScene = 1; +			gnapActionIdle(0x10C); +			gnapWalkTo(2, 9, 0, 0x107AE, 1); +			_gnapActionStatus = kASLeaveScene; +			platypusWalkTo(3, 9, -1, 0x107C7, 1); +			_newSceneNum = 9; +			break; + +		case kHSCook: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapShowCurrItem(4, 8, 6, 0); +				_gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0); +				_gnapActionStatus = kASAnnoyCook; +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playGnapScratchingHead(6, 0); +					break; +				case GRAB_CURSOR: +					playGnapImpossible(0, 0); +					_gnapIdleFacing = 1; +					break; +				case TALK_CURSOR: +					_gnapIdleFacing = 7; +					gnapActionIdle(0x10C); +					gnapWalkTo(4, 8, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +					_gnapActionStatus = kASAnnoyCook; +					break; +				case PLAT_CURSOR: +					gnapActionIdle(0x10C); +					gnapUseDeviceOnBeaver(); +					platypusWalkTo(4, 6, -1, -1, 1); +					gnapWalkTo(4, 8, 0, 0x107BB, 1); +					_gnapActionStatus = kASAnnoyCook; +					break; +				} +			} +			break; + +		case kHSTongs: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapShowCurrItem(3, 7, 4, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					if (isFlag(1)) +						playGnapMoan2(-1, -1); +					else +						playGnapScratchingHead(4, 3); +					break; +				case GRAB_CURSOR: +					if (isFlag(1)) +						playGnapMoan2(-1, -1); +					else { +						gnapActionIdle(0x10C); +						gnapWalkTo(4, 8, 0, 0x107BB, 1); +						_gnapActionStatus = kASAnnoyCook; +					} +					break; +				case TALK_CURSOR: +					playGnapImpossible(0, 0); +					break; +				case PLAT_CURSOR: +					if (isFlag(1)) +						playGnapMoan2(-1, -1); +					else { +						gnapActionIdle(0x10C); +						gnapUseDeviceOnBeaver(); +						platypusWalkTo(3, 7, -1, -1, 1); +						gnapWalkTo(4, 8, 0, 0x107BB, 1); +						_gnapActionStatus = kASAnnoyCook; +					} +					break; +				} +			} +			break; + +		case kHSBox: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapShowCurrItem(7, 6, 6, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playGnapScratchingHead(7, 3); +					break; +				case GRAB_CURSOR: +					gnapActionIdle(0x10C); +					gnapWalkTo(4, 8, 0, 0x107BB, 1); +					_gnapActionStatus = kASAnnoyCook; +					break; +				case TALK_CURSOR: +					playGnapImpossible(0, 0); +					break; +				case PLAT_CURSOR: +					if (isFlag(1)) +						playGnapMoan2(-1, -1); +					else { +						invAdd(kItemTongs); +						setFlag(1); +						gnapActionIdle(0x10C); +						gnapUseDeviceOnBeaver(); +						platypusWalkTo(7, 6, 1, 0x107D2, 1); +						_beaverActionStatus = kASPlatWithBox; +						_beaverFacing = 4; +						_largeSprite = _gameSys->createSurface(0xC3); +						playGnapIdle(7, 6); +					} +					break; +				} +			} +			break; + +		case kHSOven: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapShowCurrItem(9, 6, 10, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playGnapSequence(getGnapSequenceId(gskDeflect, 10, 5) | 0x10000); +					break; +				case GRAB_CURSOR: +					gnapActionIdle(0x10C); +					gnapWalkTo(9, 6, 0, 0x107BB, 1); +					_gameSys->insertSequence(0x10E, 120, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +					_gnapSequenceId = 0x10E; +					_gnapId = 120; +					_gnapIdleFacing = 7; +					_gnapSequenceDatNum = 0; +					_gnapX = 9; +					_gnapY = 6; +					_timers[2] = 360; +					break; +				case TALK_CURSOR: +				case PLAT_CURSOR: +					playGnapImpossible(0, 0); +					break; +				} +			} +			break; + +		case kHSWalkArea1: +		case kHSWalkArea2: +		case kHSWalkArea3: +		case kHSWalkArea4: +			gnapActionIdle(0x10C); +			gnapWalkTo(-1, -1, -1, -1, 1); +			break; + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene10_updateHotspots(); +			} +			break; +			 +		default: +			if (_mouseClickState.left) { +				gnapActionIdle(0x10C); +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; + +		} +	 +		scene10_updateAnimations(); +	 +		if (!_isLeavingScene) { +			updateBeaverIdleSequence(); +			updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = getRandom(80) + 150; +				playSound(0x12B, 0); +			} +			if (!_timers[5]) { +				int sequenceId; +				_timers[5] = getRandom(100) + 100; +				_gnapRandomValue = getRandom(4); +				if (_gnapRandomValue) { +					if (_gnapRandomValue == 1) { +						sequenceId = 0x8A5; +					} else if (_gnapRandomValue == 2) { +						sequenceId = 0x8A6; +					} else { +						sequenceId = 0x8A7; +					} +					_gameSys->insertSequence(sequenceId | 0x10000, 179, 0, 0, kSeqNone, 0, 0, 0); +				} +			} +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene10_updateHotspots(); +		} +		 +		gameUpdateTick(); +		 +	} + +} + +void GnapEngine::scene10_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASLeaveScene: +			_sceneDone = true; +			break; +		case kASAnnoyCook: +			_s10_nextCookSequenceId = 0x105; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(1) == 2) { +		_gameSys->setAnimation(0, 0, 1); +		switch (_beaverActionStatus) { +		case kASPlatWithBox: +			_s10_nextCookSequenceId = 0x109; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(2) == 2 && _s10_nextCookSequenceId != -1) { +		 +		switch (_s10_nextCookSequenceId) { +		case 0x109: +			_platX = 4; +			_platY = 8; +			_gameSys->insertSequence(0x109, 100, _s10_currCookSequenceId, 100, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x107C9, 160, +				_beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, +				kSeqSyncWait, getSequenceTotalDuration(0x109) + getSequenceTotalDuration(0x10A) + getSequenceTotalDuration(0x10843), +				75 * _platX - _platGridX, 48 * _platY - _platGridY); +			_gameSys->removeSequence(0x107, 100, 1); +			_s10_currCookSequenceId = 0x109; +			_s10_nextCookSequenceId = 0x843; +			_beaverSequenceId = 0x7C9; +			_beaverId = 160; +			_beaverFacing = 0; +			_beaverSequenceDatNum = 1; +			break; +		case 0x843: +			hideCursor(); +			_gameSys->insertSpriteDrawItem(_largeSprite, 0, 0, 300); +			_gameSys->insertSequence(0x10843, 301, _s10_currCookSequenceId, 100, kSeqSyncWait, 0, 0, 0); +			_s10_currCookSequenceId = 0x843; +			_s10_nextCookSequenceId = 0x10A; +			break; +		case 0x10A: +			_gameSys->insertSequence(_s10_nextCookSequenceId, 100, 0x10843, 301, kSeqSyncWait, 0, 0, 0); +			_s10_currCookSequenceId = _s10_nextCookSequenceId; +			_s10_nextCookSequenceId = 0x104; +			showCursor(); +			_gameSys->removeSpriteDrawItem(_largeSprite, 300); +			delayTicksCursor(5); +			deleteSurface(&_largeSprite); +			setGrabCursorSprite(kItemTongs); +			if (_beaverActionStatus == kASPlatWithBox) +				_beaverActionStatus = -1; +			if (_gnapX == 4 && _gnapY == 8) +				gnapWalkStep(); +			break; +		default: +			_gameSys->insertSequence(_s10_nextCookSequenceId, 100, _s10_currCookSequenceId, 100, kSeqSyncWait, 0, 0, 0); +			_s10_currCookSequenceId = _s10_nextCookSequenceId; +			break; +		} +	 +		switch (_s10_currCookSequenceId) { +		case 0x106: +			_gnapRandomValue = getRandom(7); +			if (_gnapActionStatus >= 0 || _beaverActionStatus >= 0) +				_s10_nextCookSequenceId = 0x106; +			else if (_gnapRandomValue == 0) +				_s10_nextCookSequenceId = 0x104; +			else if (_gnapRandomValue == 1) +				_s10_nextCookSequenceId = 0x103; +			else if (_gnapRandomValue == 2) { +				_s10_nextCookSequenceId = 0x106; +				_gameSys->insertSequence(0x10D, 1, 0, 0, kSeqNone, 0, 0, 0); +			} else +				_s10_nextCookSequenceId = 0x106; +			break; +		case 0x103: +			_gnapRandomValue = getRandom(7); +			if (_gnapActionStatus >= 0 || _beaverActionStatus >= 0) +				_s10_nextCookSequenceId = 0x106; +			else if (_gnapRandomValue == 0) +				_s10_nextCookSequenceId = 0x104; +			else +				_s10_nextCookSequenceId = 0x106; +			break; +		case 0x104: +			_gnapRandomValue = getRandom(7); +			if (_gnapActionStatus >= 0 || _beaverActionStatus >= 0) +				_s10_nextCookSequenceId = 0x106; +			else if (_gnapRandomValue == 0) +				_s10_nextCookSequenceId = 0x103; +			else +				_s10_nextCookSequenceId = 0x106; +			break; +		case 0x105: +			_gnapRandomValue = getRandom(7); +			if (_gnapActionStatus >= 0 || _beaverActionStatus >= 0) +				_s10_nextCookSequenceId = 0x106; +			else if (_gnapRandomValue == 0) +				_s10_nextCookSequenceId = 0x104; +			else if (_gnapRandomValue == 1) +				_s10_nextCookSequenceId = 0x103; +			else +				_s10_nextCookSequenceId = 0x106; +			_timers[2] = getRandom(30) + 20; +			_timers[3] = 300; +			_gameSys->insertSequence(0x10C, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x10C; +			_gnapIdleFacing = 7; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = -1; +			_beaverActionStatus = -1; +			break; +		} +		if (_s10_currCookSequenceId == 0x843) +			_gameSys->setAnimation(_s10_currCookSequenceId | 0x10000, 301, 2); +		else +			_gameSys->setAnimation(_s10_currCookSequenceId, 100, 2); +	} + +} + +void GnapEngine::scene10_updateAnimationsCb() { +	if (_gameSys->getAnimationStatus(2) == 2) { +		_gameSys->setAnimation(_s10_nextCookSequenceId, 100, 2); +		_gameSys->insertSequence(_s10_nextCookSequenceId, 100, _s10_currCookSequenceId, 100, kSeqSyncWait, 0, 0, 0); +		_s10_currCookSequenceId = _s10_nextCookSequenceId; +		_s10_nextCookSequenceId = 0x106; +	} +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene11.cpp b/engines/gnap/scenes/scene11.cpp new file mode 100644 index 0000000000..6bbc542e90 --- /dev/null +++ b/engines/gnap/scenes/scene11.cpp @@ -0,0 +1,488 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSExitKitchen	= 1, +	kHSExitToilet	= 2, +	kHSExitLeft		= 3, +	kHSGoggleGuy	= 4, +	kHSHookGuy		= 5, +	kHSBillard		= 6, +	kHSWalkArea1	= 7, +	kHSDevice		= 8, +	kHSWalkArea2	= 9, +	kHSWalkArea3	= 10, +	kHSWalkArea4	= 11, +	kHSWalkArea5	= 12 +}; + +enum { +	kASLeaveScene				= 0, +	kASShowMagazineToGoggleGuy	= 3, +	kASTalkGoggleGuy			= 4, +	kASGrabHookGuy				= 6, +	kASShowItemToHookGuy		= 8, +	kASTalkHookGuy				= 9, +	kASGrabBillardBall			= 11 +}; + +int GnapEngine::scene11_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 3); +	_gameSys->setAnimation(0, 0, 2); +	if (_prevSceneNum == 10 || _prevSceneNum == 13) { +		playSound(0x108EC, 0); +		playSound(0x10928, 0); +	} +	return 0x209; +} + +void GnapEngine::scene11_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitKitchen, 420, 140, 520, 345, SF_EXIT_U_CURSOR); +	setHotspot(kHSExitToilet, 666, 130, 740, 364, SF_EXIT_R_CURSOR); +	setHotspot(kHSExitLeft, 0, 350, 10, 599, SF_EXIT_L_CURSOR | SF_WALKABLE); +	setHotspot(kHSGoggleGuy, 90, 185, 185, 340, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSHookGuy, 210, 240, 340, 430, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSBillard, 640, 475, 700, 530, SF_WALKABLE | SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSWalkArea1, 0, 0, 365, 453); +	setHotspot(kHSWalkArea2, 0, 0, 629, 353); +	setHotspot(kHSWalkArea3, 629, 0, 799, 364); +	setHotspot(kHSWalkArea4, 735, 0, 799, 397); +	setHotspot(kHSWalkArea5, 510, 540, 799, 599); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 13; +} + +void GnapEngine::scene11_run() { +	bool flag = true; +	 +	_timers[7] = 50; +	 +	_hotspots[kHSBillard].flags |= SF_DISABLED; +	 +	_s11_currGoggleGuySequenceId = 0x1F9; +	 +	_s11_currHookGuySequenceId = 0x201; +	 +	switch (_prevSceneNum) { +	case 13: +		initGnapPos(8, 5, 3); +		initBeaverPos(9, 6, 4); +		break; +	case 47: +		initGnapPos(8, 5, 3); +		initBeaverPos(9, 5, 4); +		_s11_currGoggleGuySequenceId = 0x1FA; +		_s11_currHookGuySequenceId = 0x1FF; +		_timers[7] = 180; +		break; +	case 12: +		initGnapPos(-1, 9, 1); +		initBeaverPos(-2, 8, 0); +		break; +	default: +		initGnapPos(6, 6, 3); +		initBeaverPos(6, 5, 4); +		break; +	} +	 +	queueInsertDeviceIcon(); +	 +	_gameSys->insertSequence(_s11_currHookGuySequenceId, 120, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s11_nextHookGuySequenceId = -1; +	 +	_gameSys->setAnimation(_s11_currHookGuySequenceId, 120, 3); +	_gameSys->insertSequence(_s11_currGoggleGuySequenceId, 121, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s11_nextGoggleGuySequenceId = -1; +	 +	_gameSys->setAnimation(_s11_currGoggleGuySequenceId, 121, 2); +	 +	_timers[5] = getRandom(100) + 75; +	_timers[4] = getRandom(40) + 20; +	_timers[6] = getRandom(100) + 100; +	endSceneInit(); +	 +	if (_prevSceneNum == 12) { +		gnapWalkTo(2, 8, -1, 0x107B9, 1); +		platypusWalkTo(1, 8, -1, 0x107C2, 1); +	} + +	_gameSys->insertSequence(0x208, 256, 0, 0, kSeqNone, 40, 0, 0); +	 +	while (!_sceneDone) { +	 +		testWalk(0, 0, -1, -1, -1, -1); +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSPlatypus: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapImpossible(0, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playGnapMoan1(_platX, _platY); +					break; +				case GRAB_CURSOR: +					gnapKissPlatypus(0); +					break; +				case TALK_CURSOR: +					playGnapBrainPulsating(_platX, _platY); +					playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +					break; +				case PLAT_CURSOR: +					break; +				} +			} +			break; + +		case kHSExitKitchen: +			_isLeavingScene = true; +			gnapWalkTo(6, 5, 0, 0x107BF, 1); +			_gnapActionStatus = kASLeaveScene; +			platypusWalkTo(6, 6, -1, -1, 1); +			_newSceneNum = 10; +			break; + +		case kHSExitToilet: +			_isLeavingScene = true; +			gnapWalkTo(8, 5, 0, 0x107BF, 1); +			_gnapActionStatus = kASLeaveScene; +			platypusWalkTo(8, 6, -1, -1, 1); +			_newSceneNum = 13; +			break; + +		case kHSExitLeft: +			_isLeavingScene = true; +			gnapWalkTo(-1, 8, 0, 0x107AF, 1); +			_gnapActionStatus = kASLeaveScene; +			platypusWalkTo(-1, 9, -1, 0x107CF, 1); +			_newSceneNum = 12; +			break; + +		case kHSGoggleGuy: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemMagazine) { +					gnapWalkTo(3, 7, 0, 0x107BC, 1); +					_gnapActionStatus = kASShowMagazineToGoggleGuy; +					playGnapShowItem(_grabCursorSpriteIndex, 2, 0); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(3, 7, 2, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(1, 6); +						break; +					case GRAB_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 5; +						gnapWalkTo(3, 7, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASTalkGoggleGuy; +						break; +					} +				} +			} +			break; + +		case kHSHookGuy: +			if (_gnapActionStatus < 0) { +				_gnapIdleFacing = 7; +				if (_grabCursorSpriteIndex >= 0) { +					gnapWalkTo(5, 6, 0, 0x107BC, 9); +					_gnapActionStatus = kASShowItemToHookGuy; +					playGnapShowItem(_grabCursorSpriteIndex, 4, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapSequence(getGnapSequenceId(gskDeflect, 3, 6) | 0x10000); +						break; +					case GRAB_CURSOR: +						gnapWalkTo(5, 6, 0, 0x107BC, 1); +						_gnapActionStatus = kASGrabHookGuy; +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 3; +						gnapWalkTo(5, 6, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASTalkHookGuy; +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSBillard: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(9, 8); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(9, 8); +						break; +					case GRAB_CURSOR: +						gnapWalkTo(9, 8, 0, 0x107BA, 1); +						_gnapActionStatus = kASGrabBillardBall; +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(9, 8); +						break; +					} +				} +			} +			break; + +		case kHSWalkArea1: +		case kHSWalkArea2: +		case kHSWalkArea3: +		case kHSWalkArea4: +		case kHSWalkArea5: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene11_updateHotspots(); +			} +			break; +			 +		default: +			if (_mouseClickState.left && _gnapActionStatus < 0) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +			 +		} + +		scene11_updateAnimations(); +	 +		if (!_isLeavingScene) { +			if (flag && !_timers[7]) { +				flag = false; +				_gameSys->setAnimation(0x207, 257, 4); +				_gameSys->insertSequence(0x207, 257, 0, 0, kSeqNone, 0, 0, 0); +			} +			beaverSub426234(); +			updateGnapIdleSequence2(); +			if (!_timers[5]) { +				_timers[5] = getRandom(100) + 75; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s11_nextGoggleGuySequenceId == -1) { +					_gnapRandomValue = getRandom(2); +					if (_gnapRandomValue) +						_s11_nextGoggleGuySequenceId = 0x1F6; +					else +						_s11_nextGoggleGuySequenceId = 0x1F9; +				} +			} +			if (!_timers[4]) { +				_timers[4] = getRandom(40) + 20; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s11_nextHookGuySequenceId == -1) { +					if (_s11_currHookGuySequenceId == 0x201) { +						_gnapRandomValue = getRandom(7); +						switch (_gnapRandomValue) { +						case 0: +							_s11_nextHookGuySequenceId = 0x200; +							break; +						case 1: +							_s11_nextHookGuySequenceId = 0x205; +							break; +						case 2: +							_s11_nextHookGuySequenceId = 0x202; +							break; +						default: +							_s11_nextHookGuySequenceId = 0x201; +							break; +						} +					} else { +						_s11_nextHookGuySequenceId = 0x201; +					} +				} +			} +			if (!_timers[6]) { +				_timers[6] = getRandom(100) + 100; +				_gnapRandomValue = getRandom(3); +				switch (_gnapRandomValue) { +				case 0: +					_gameSys->insertSequence(0x8A5 | 0x10000, 179, 0, 0, kSeqNone, 0, 0, 0); +					break; +				case 1: +					_gameSys->insertSequence(0x8A7 | 0x10000, 179, 0, 0, kSeqNone, 0, 0, 0); +					break; +				case 2: +					_gameSys->insertSequence(0x8A6 | 0x10000, 179, 0, 0, kSeqNone, 0, 0, 0); +					break; +				} +			} +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene11_updateHotspots(); +			_timers[5] = getRandom(50) + 75; +			_timers[4] = getRandom(40) + 20; +		} +		 +		gameUpdateTick(); +	 +	} +   +} + +void GnapEngine::scene11_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		if (_gnapActionStatus != kASGrabBillardBall) +			_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASLeaveScene: +			_sceneDone = true; +			break; +		case kASShowMagazineToGoggleGuy: +			_s11_nextGoggleGuySequenceId = 0x1F7; +			break; +		case kASTalkGoggleGuy: +			_s11_nextGoggleGuySequenceId = 0x1FB; +			break; +		case kASGrabHookGuy: +			_s11_nextHookGuySequenceId = 0x204; +			break; +		case kASShowItemToHookGuy: +			_s11_nextHookGuySequenceId = 0x203; +			break; +		case kASTalkHookGuy: +			_s11_nextHookGuySequenceId = 0x206; +			break; +		case kASGrabBillardBall: +			if (_gameSys->getAnimationStatus(2) == 2 && _gameSys->getAnimationStatus(3) == 2) { +				_gameSys->setAnimation(0, 0, 0); +				_timers[2] = getRandom(30) + 20; +				_timers[3] = getRandom(50) + 200; +				_gameSys->insertSequence(0x1F4, 255, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +				_gnapSequenceId = 0x1F4; +				_gnapId = 255; +				_gnapSequenceDatNum = 0; +				_gameSys->removeSequence(0x207, 257, 1); +				_gameSys->removeSequence(0x208, 256, 1); +				_s11_nextGoggleGuySequenceId = 0x1F8; +				_timers[5] = getRandom(100) + 75; +				_gameSys->insertSequence(_s11_nextGoggleGuySequenceId, 121, _s11_currGoggleGuySequenceId, 121, kSeqSyncWait, 0, 0, 0); +				_gameSys->setAnimation(_s11_nextGoggleGuySequenceId, 121, 2); +				_s11_currGoggleGuySequenceId = _s11_nextGoggleGuySequenceId; +				_s11_nextGoggleGuySequenceId = -1; +				switch (_s11_billardBallCtr) { +				case 0: +					_s11_nextHookGuySequenceId = 0x1FC; +					break; +				case 1: +					_s11_nextHookGuySequenceId = 0x1FD; +					break; +				default: +					_s11_nextHookGuySequenceId = 0x1FE; +					break; +				} +				++_s11_billardBallCtr; +				_gameSys->insertSequence(_s11_nextHookGuySequenceId, 120, _s11_currHookGuySequenceId, 120, kSeqSyncWait, 0, 0, 0); +				_gameSys->setAnimation(_s11_nextHookGuySequenceId, 120, 3); +				_s11_currHookGuySequenceId = _s11_nextHookGuySequenceId; +				_s11_nextHookGuySequenceId = -1; +				_timers[4] = getRandom(40) + 20; +				_gameSys->insertSequence(0x208, 256, 0, 0, kSeqNone, getSequenceTotalDuration(0x1F4) - 5, 0, 0); +				_hotspots[kHSBillard].flags |= SF_DISABLED; +				_gameSys->setAnimation(0x207, 257, 4); +				_gameSys->insertSequence(0x207, 257, 0, 0, kSeqNone, getSequenceTotalDuration(0x1FE), 0, 0); +				_gnapActionStatus = -1; +			} +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(2) == 2 && _s11_nextGoggleGuySequenceId != -1) { +		_timers[5] = getRandom(100) + 75; +		_gameSys->insertSequence(_s11_nextGoggleGuySequenceId, 121, _s11_currGoggleGuySequenceId, 121, kSeqSyncWait, 0, 0, 0); +		_gameSys->setAnimation(_s11_nextGoggleGuySequenceId, 121, 2); +		_s11_currGoggleGuySequenceId = _s11_nextGoggleGuySequenceId; +		_s11_nextGoggleGuySequenceId = -1; +		if (_gnapActionStatus >= 1 && _gnapActionStatus <= 4) +			_gnapActionStatus = -1; +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2) { +		if (_s11_nextHookGuySequenceId == 0x204) { +			_gameSys->setAnimation(_s11_nextHookGuySequenceId, 120, 3); +			_gameSys->insertSequence(0x204, 120, _s11_currHookGuySequenceId, 120, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x1F5, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_s11_currHookGuySequenceId = 0x204; +			_s11_nextHookGuySequenceId = -1; +			_gnapSequenceId = 0x1F5; +			_gnapSequenceDatNum = 0; +			_timers[4] = getRandom(40) + 20; +			_timers[2] = getRandom(20) + 70; +			_timers[3] = getRandom(50) + 200; +			if (_gnapActionStatus == kASGrabHookGuy) +				_gnapActionStatus = -1; +		} else if (_s11_nextHookGuySequenceId != -1) { +			_gameSys->insertSequence(_s11_nextHookGuySequenceId, 120, _s11_currHookGuySequenceId, 120, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s11_nextHookGuySequenceId, 120, 3); +			_s11_currHookGuySequenceId = _s11_nextHookGuySequenceId; +			_s11_nextHookGuySequenceId = -1; +			_timers[4] = getRandom(40) + 20; +			if (_gnapActionStatus >= 6 && _gnapActionStatus <= 9) +				_gnapActionStatus = -1; +		} +	} +	 +	if (_gameSys->getAnimationStatus(4) == 2) { +		_gameSys->setAnimation(0, 0, 4); +		_hotspots[kHSBillard].flags &= ~SF_DISABLED; +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene12.cpp b/engines/gnap/scenes/scene12.cpp new file mode 100644 index 0000000000..076fa0408d --- /dev/null +++ b/engines/gnap/scenes/scene12.cpp @@ -0,0 +1,564 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSExitRight	= 1, +	kHSToothGuy		= 2, +	kHSBarkeeper	= 3, +	kHSBeardGuy		= 4, +	kHSJukebox		= 5, +	kHSWalkArea1	= 6, +	kHSDevice		= 7, +	kHSWalkArea2	= 8, +	kHSWalkArea3	= 9, +	kHSWalkArea4	= 10 +}; + +enum { +	kASLeaveScene					= 0, +	kASQuarterToToothGuyDone		= 1, +	kASTalkToothGuy					= 2, +	kASGrabToothGuy					= 4, +	kASShowItemToToothGuy			= 5, +	kASQuarterWithHoleToToothGuy	= 6, +	kASQuarterToToothGuy			= 7, +	kASTalkBeardGuy					= 8, +	kASLookBeardGuy					= 9, +	kASGrabBeardGuy					= 10, +	kASShowItemToBeardGuy			= 11, +	kASTalkBarkeeper				= 12, +	kASLookBarkeeper				= 13, +	kASShowItemToBarkeeper			= 15, +	kASQuarterWithBarkeeper			= 16, +	kASPlatWithBarkeeper			= 17, +	kASPlatWithToothGuy				= 18, +	kASPlatWithBeardGuy				= 19 +}; + +int GnapEngine::scene12_init() { +	return 0x209; +} + +void GnapEngine::scene12_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitRight, 790, 360, 799, 599, SF_EXIT_R_CURSOR); +	setHotspot(kHSToothGuy, 80, 180, 160, 380, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSBarkeeper, 490, 175, 580, 238, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSBeardGuy, 620, 215, 720, 350, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSJukebox, 300, 170, 410, 355, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSWalkArea1, 0, 0, 260, 460); +	setHotspot(kHSWalkArea2, 0, 0, 380, 410); +	setHotspot(kHSWalkArea3, 0, 0, 799, 395); +	setHotspot(kHSWalkArea4, 585, 0, 799, 455); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 11; +} + +void GnapEngine::scene12_run() { +	int v18 = 1; + +	queueInsertDeviceIcon(); + +	_gameSys->insertSequence(0x207, 256, 0, 0, kSeqNone, 0, 0, 0); +	_gameSys->insertSequence(0x200, 50, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s12_currToothGuySequenceId = 0x200; +	_s12_nextToothGuySequenceId = -1; +	 +	_gameSys->setAnimation(0x200, 50, 2); +	_gameSys->insertSequence(0x202, 50, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s12_currBeardGuySequenceId = 0x202; +	_s12_nextBeardGuySequenceId = -1; +	 +	_gameSys->setAnimation(0x202, 50, 4); +	_gameSys->insertSequence(0x203, 50, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s12_currBarkeeperSequenceId = 0x203; +	_s12_nextBarkeeperSequenceId = -1; +	 +	_gameSys->setAnimation(0x203, 50, 3); +	 +	_timers[4] = 30; +	_timers[6] = getRandom(30) + 20; +	_timers[5] = getRandom(30) + 20; +	_timers[7] = getRandom(100) + 100; +	 +	if (_prevSceneNum == 15) { +		initGnapPos(5, 6, 1); +		initBeaverPos(3, 7, 0); +		endSceneInit(); +	} else { +		initGnapPos(11, 8, 3); +		initBeaverPos(12, 8, 4); +		endSceneInit(); +		gnapWalkTo(8, 8, -1, 0x107BA, 1); +		platypusWalkTo(9, 8, -1, 0x107D2, 1); +	} + +	while (!_sceneDone) { +	 +		testWalk(0, 0, -1, -1, -1, -1); +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +		updateGrabCursorSprite(0, 0); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene12_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			switch (_verbCursor) { +			case LOOK_CURSOR: +				playGnapMoan1(_platX, _platY); +				break; +			case GRAB_CURSOR: +				gnapKissPlatypus(0); +				break; +			case TALK_CURSOR: +				playGnapBrainPulsating(_platX, _platY); +				playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +				break; +			case PLAT_CURSOR: +				break; +			} +			break; + +		case kHSExitRight: +			_isLeavingScene = 1; +			gnapWalkTo(10, -1, 0, 0x107AB, 1); +			_gnapActionStatus = kASLeaveScene; +			platypusWalkTo(10, -1, -1, -1, 1); +			_newSceneNum = 11; +			break; + +		case kHSToothGuy: +			if (_grabCursorSpriteIndex == kItemQuarter) { +				_largeSprite = _gameSys->createSurface(0x141); +				gnapWalkTo(3, 7, 0, 0x107BC, 9); +				_gnapIdleFacing = 5; +				_gnapActionStatus = kASQuarterToToothGuy; +				playGnapShowItem(_grabCursorSpriteIndex, 2, 0); +				setGrabCursorSprite(-1); +			} else if (_grabCursorSpriteIndex == kItemQuarterWithHole) { +				gnapWalkTo(3, 7, 0, 0x107BC, 9); +				_gnapIdleFacing = 5; +				_gnapActionStatus = kASQuarterWithHoleToToothGuy; +				playGnapShowItem(_grabCursorSpriteIndex, 2, 0); +			} else if (_grabCursorSpriteIndex >= 0) { +				gnapWalkTo(3, 7, 0, 0x107BC, 9); +				_gnapIdleFacing = 5; +				_gnapActionStatus = kASShowItemToToothGuy; +				playGnapShowItem(_grabCursorSpriteIndex, 2, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playGnapScratchingHead(1, 2); +					break; +				case GRAB_CURSOR: +					gnapWalkTo(3, 7, 0, 0x107BC, 1); +					_gnapActionStatus = kASGrabToothGuy; +					break; +				case TALK_CURSOR: +					_gnapIdleFacing = 5; +					gnapWalkTo(3, 7, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +					_gnapActionStatus = kASTalkToothGuy; +					break; +				case PLAT_CURSOR: +					gnapUseDeviceOnBeaver(); +					platypusWalkTo(3, 7, 1, 0x107D2, 1); +					_beaverActionStatus = kASPlatWithToothGuy; +					_beaverFacing = 4; +					playGnapIdle(2, 7); +					break; +				} +			} +			break; + +		case kHSBarkeeper: +			if (_grabCursorSpriteIndex == kItemQuarter || _grabCursorSpriteIndex == kItemQuarterWithHole) { +				gnapWalkTo(6, 6, 0, 0x107BB, 9); +				_gnapIdleFacing = 7; +				_gnapActionStatus = kASQuarterWithBarkeeper; +				playGnapShowItem(_grabCursorSpriteIndex, 7, 0); +			} else if (_grabCursorSpriteIndex >= 0) { +				gnapWalkTo(6, 6, 0, 0x107BB, 9); +				_gnapIdleFacing = 7; +				_gnapActionStatus = kASShowItemToBarkeeper; +				playGnapShowItem(_grabCursorSpriteIndex, 7, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					gnapWalkTo(6, 6, 0, 0x107BB, 1); +					_gnapIdleFacing = 7; +					_gnapActionStatus = kASLookBarkeeper; +					break; +				case GRAB_CURSOR: +					playGnapImpossible(0, 0); +					break; +				case TALK_CURSOR: +					_gnapIdleFacing = 7; +					gnapWalkTo(6, 6, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +					_gnapActionStatus = kASTalkBarkeeper; +					break; +				case PLAT_CURSOR: +					playGnapPullOutDevice(_platX, _platY); +					_gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0); +					_gnapActionStatus = kASPlatWithBarkeeper; +					break; +				} +			} +			break; + +		case kHSBeardGuy: +			if (_grabCursorSpriteIndex >= 0) { +				gnapWalkTo(7, 6, 0, 0x107BB, 9); +				_gnapIdleFacing = 7; +				_gnapActionStatus = kASShowItemToBeardGuy; +				playGnapShowItem(_grabCursorSpriteIndex, 8, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					gnapWalkTo(7, 6, 0, 0x107BB, 1); +					_gnapIdleFacing = 7; +					_gnapActionStatus = kASLookBeardGuy; +					break; +				case GRAB_CURSOR: +					// NOTE Bug in the original. It has 9 as flags which seems wrong here. +					gnapWalkTo(7, 6, 0, 0x107BB, 1); +					_gnapIdleFacing = 7; +					_gnapActionStatus = kASGrabBeardGuy; +					break; +				case TALK_CURSOR: +					_gnapIdleFacing = 7; +					gnapWalkTo(7, 6, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +					_gnapActionStatus = kASTalkBeardGuy; +					break; +				case PLAT_CURSOR: +					gnapUseDeviceOnBeaver(); +					platypusWalkTo(7, 6, 1, 0x107C2, 1); +					_beaverActionStatus = kASPlatWithBeardGuy; +					_beaverFacing = 0; +					playGnapIdle(7, 6); +					break; +				} +			} +			break; + +		case kHSJukebox: +			_newSceneNum = 15; +			_isLeavingScene = 1; +			gnapWalkTo(5, 6, 0, 0x107BC, 1); +			_gnapActionStatus = kASLeaveScene; +			break; + +		case kHSWalkArea1: +		case kHSWalkArea2: +		case kHSWalkArea3: +		case kHSWalkArea4: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; + +		default: +			if (_mouseClickState.left && _gnapActionStatus < 0) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; + +		} +	 +		scene12_updateAnimations(); +	 +		if (!_isLeavingScene) { +			updateBeaverIdleSequence(); +			updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = 15; +				if (_s12_nextToothGuySequenceId == -1) { +					if (v18 == 0 && _s12_currBeardGuySequenceId == 0x202 && _s12_currBarkeeperSequenceId == 0x203 && _gnapActionStatus < 0 && _beaverActionStatus < 0) { +						if (getRandom(2) != 0) +							_s12_nextToothGuySequenceId = 0x1EC; +						else +							_s12_nextToothGuySequenceId = 0x204; +					} else if (_s12_currToothGuySequenceId != 0x200) +						_s12_nextToothGuySequenceId = 0x200; +					v18 = (v18 + 1) % 15; +				} +			} +			if (!_timers[5]) { +				_timers[5] = getRandom(30) + 20; +				if (_s12_nextBarkeeperSequenceId == -1 && _gnapActionStatus < 0 && _beaverActionStatus < 0) { +					if (v18 == 0 && _s12_currToothGuySequenceId == 0x200 && _s12_currBeardGuySequenceId == 0x202 && _gnapActionStatus < 0 && _beaverActionStatus < 0) { +						if (getRandom(2) != 0) +							_s12_nextBarkeeperSequenceId = 0x208; +						else +							_s12_nextBarkeeperSequenceId = 0x1FB; +					} else +						_s12_nextBarkeeperSequenceId = 0x203; +					v18 = (v18 + 1) % 15; +				} +			} +			if (!_timers[6]) { +				_timers[6] = getRandom(30) + 15; +				if (_s12_nextBeardGuySequenceId == -1 && _gnapActionStatus < 0 && _beaverActionStatus < 0) { +					if (v18 == 0 && _s12_currToothGuySequenceId == 0x200 && _s12_currBarkeeperSequenceId == 0x203 && _gnapActionStatus < 0 && _beaverActionStatus < 0) +						_s12_nextBeardGuySequenceId = 0x1F2; +					else +						_s12_nextBeardGuySequenceId = 0x202; +					v18 = (v18 + 1) % 15; +				} +			} +			if (!_timers[7]) { +				_timers[7] = getRandom(100) + 100; +				_gnapRandomValue = getRandom(3); +				switch (_gnapRandomValue) { +				case 0: +					_gameSys->insertSequence(0x8A5 | 0x10000, 179, 0, 0, kSeqNone, 0, 0, 0); +					break; +				case 1: +					_gameSys->insertSequence(0x8A7 | 0x10000, 179, 0, 0, kSeqNone, 0, 0, 0); +					break; +				case 2: +					_gameSys->insertSequence(0x8A6 | 0x10000, 179, 0, 0, kSeqNone, 0, 0, 0); +					break; +				} +			} +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene12_updateHotspots(); +			_timers[4] = 30; +			_timers[5] = getRandom(30) + 20; +			_timers[6] = getRandom(30) + 20; +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene12_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASLeaveScene: +			_sceneDone = true; +			break; +		case kASTalkToothGuy: +			if (isKeyStatus1(Common::KEYCODE_j)) { +				// Easter egg +				clearKeyStatus1(Common::KEYCODE_j); +				_s12_nextToothGuySequenceId = 0x206; +			} else { +				_s12_nextToothGuySequenceId = 0x1EE; +			} +			break; +		case 3: +			break; +		case kASGrabToothGuy: +			if (isKeyStatus1(Common::KEYCODE_j)) { +				clearKeyStatus1(Common::KEYCODE_j); +				_s12_nextToothGuySequenceId = 0x206; +			} else { +				_s12_nextToothGuySequenceId = 0x1EF; +			} +			break; +		case kASShowItemToToothGuy: +			if (isKeyStatus1(Common::KEYCODE_j)) { +				clearKeyStatus1(Common::KEYCODE_j); +				_s12_nextToothGuySequenceId = 0x206; +			} else { +				_s12_nextToothGuySequenceId = 0x1ED; +			} +			break; +		case kASQuarterWithHoleToToothGuy: +			if (isKeyStatus1(Common::KEYCODE_j)) { +				clearKeyStatus1(Common::KEYCODE_j); +				_s12_nextToothGuySequenceId = 0x206; +			} else { +				_s12_nextToothGuySequenceId = 0x1EA; +			} +			break; +		case kASQuarterToToothGuy: +			if (isKeyStatus1(Common::KEYCODE_j)) { +				clearKeyStatus1(Common::KEYCODE_j); +				_s12_nextToothGuySequenceId = 0x206; +			} else { +				_s12_nextToothGuySequenceId = 0x1E9; +			} +			break; +		case kASQuarterToToothGuyDone: +			_gnapActionStatus = -1; +			showCursor(); +			_gameSys->removeSpriteDrawItem(_largeSprite, 300); +			deleteSurface(&_largeSprite); +			setGrabCursorSprite(kItemQuarterWithHole); +			break; +		case kASTalkBeardGuy: +			_s12_nextBeardGuySequenceId = 0x1F4; +			break; +		case kASLookBeardGuy: +			_s12_nextBeardGuySequenceId = 0x1F3; +			break; +		case kASGrabBeardGuy: +			_s12_nextBeardGuySequenceId = 0x1F1; +			break; +		case kASShowItemToBeardGuy: +			_s12_nextBeardGuySequenceId = 0x1F0; +			break; +		case kASTalkBarkeeper: +			_gnapRandomValue = getRandom(2); +			if (_gnapRandomValue != 0) +				_s12_nextBarkeeperSequenceId = 0x1FD; +			else +				_s12_nextBarkeeperSequenceId = 0x1FF; +			break; +		case kASLookBarkeeper: +			_s12_nextBarkeeperSequenceId = 0x1F8; +			break; +		case 14: +			_s12_nextBarkeeperSequenceId = 0x1F6; +			break; +		case kASShowItemToBarkeeper: +			_s12_nextBarkeeperSequenceId = 0x1F5; +			break; +		case kASQuarterWithBarkeeper: +			_s12_nextBarkeeperSequenceId = 0x1FA; +			break; +		case kASPlatWithBarkeeper: +			_s12_nextBarkeeperSequenceId = 0x1F9; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(1) == 2) { +		_gameSys->setAnimation(0, 0, 1); +		switch (_beaverActionStatus) { +		case kASPlatWithToothGuy: +			_s12_nextToothGuySequenceId = 0x1EB; +			break; +		case kASPlatWithBeardGuy: +			_s12_nextBeardGuySequenceId = 0x1F3; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(2) == 2) { +		if (_s12_currToothGuySequenceId == 0x1E9) { +			_gameSys->setAnimation(0, 0, 2); +			hideCursor(); +			_gameSys->setAnimation(0x10843, 301, 0); +			_gnapActionStatus = kASQuarterToToothGuyDone; +			_gameSys->insertSpriteDrawItem(_largeSprite, 0, 0, 300); +			_gameSys->insertSequence(0x10843, 301, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x107B7, _gnapId, 0x10843, 301, +				kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +			_gnapSequenceId = 0x7B7; +			_gnapSequenceDatNum = 1; +			setFlag(3); +			invAdd(kItemQuarterWithHole); +			invRemove(kItemQuarter); +		} +		if (_s12_nextToothGuySequenceId == 0x1EF) { +			_gameSys->setAnimation(_s12_nextToothGuySequenceId, 50, 2); +			_gameSys->insertSequence(_s12_nextToothGuySequenceId, 50, _s12_currToothGuySequenceId, 50, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x205, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_s12_currToothGuySequenceId = _s12_nextToothGuySequenceId; +			_s12_nextToothGuySequenceId = -1; +			_gnapSequenceId = 0x205; +			_gnapSequenceDatNum = 0; +			_timers[4] = 40; +			_timers[2] = getRandom(20) + 70; +			_timers[3] = getRandom(50) + 200; +			if (_gnapActionStatus == kASGrabToothGuy) +				_gnapActionStatus = -1; +		} else if (_s12_nextToothGuySequenceId != -1) { +			_gameSys->insertSequence(_s12_nextToothGuySequenceId, 50, _s12_currToothGuySequenceId, 50, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s12_nextToothGuySequenceId, 50, 2); +			_s12_currToothGuySequenceId = _s12_nextToothGuySequenceId; +			_s12_nextToothGuySequenceId = -1; +			_timers[4] = 50; +			if (_gnapActionStatus >= kASTalkToothGuy && _gnapActionStatus <= kASQuarterToToothGuy && _s12_currToothGuySequenceId != 0x1E9 && +				_s12_currToothGuySequenceId != 0x1EC && _s12_currToothGuySequenceId != 0x200) +				_gnapActionStatus = -1; +			if (_beaverActionStatus == kASPlatWithToothGuy) +				_beaverActionStatus = -1; +		} +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2) { +		if (_gnapActionStatus == kASPlatWithBarkeeper && _s12_currBarkeeperSequenceId == 0x1F9) { +			_gnapActionStatus = -1; +			playGnapIdle(7, 6); +			_timers[5] = 0; +		} +		if (_s12_nextBarkeeperSequenceId != -1) { +			_gameSys->insertSequence(_s12_nextBarkeeperSequenceId, 50, _s12_currBarkeeperSequenceId, 50, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s12_nextBarkeeperSequenceId, 50, 3); +			_s12_currBarkeeperSequenceId = _s12_nextBarkeeperSequenceId; +			_s12_nextBarkeeperSequenceId = -1; +			_timers[5] = getRandom(30) + 20; +			if (_gnapActionStatus >= kASTalkBarkeeper && _gnapActionStatus <= kASQuarterWithBarkeeper && _s12_currBarkeeperSequenceId != 0x203 && +				_s12_currBarkeeperSequenceId != 0x1FB && _s12_currBarkeeperSequenceId != 0x208) +				_gnapActionStatus = -1; +		} +	} +	 +	if (_gameSys->getAnimationStatus(4) == 2 && _s12_nextBeardGuySequenceId != -1) { +		_gameSys->insertSequence(_s12_nextBeardGuySequenceId, 50, _s12_currBeardGuySequenceId, 50, kSeqSyncWait, 0, 0, 0); +		_gameSys->setAnimation(_s12_nextBeardGuySequenceId, 50, 4); +		_s12_currBeardGuySequenceId = _s12_nextBeardGuySequenceId; +		_s12_nextBeardGuySequenceId = -1; +		_timers[6] = getRandom(30) + 20; +		if (_gnapActionStatus >= kASTalkBeardGuy && _gnapActionStatus <= kASShowItemToBeardGuy && _s12_currBeardGuySequenceId != 0x202 && _s12_currBeardGuySequenceId != 0x1F2) +			_gnapActionStatus = -1; +		if (_beaverActionStatus == kASPlatWithBeardGuy) +			_beaverActionStatus = -1; +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene13.cpp b/engines/gnap/scenes/scene13.cpp new file mode 100644 index 0000000000..c9b4d53917 --- /dev/null +++ b/engines/gnap/scenes/scene13.cpp @@ -0,0 +1,455 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSExitBar		= 1, +	kHSWalkArea1	= 2, +	kHSBackToilet	= 3, +	kHSFrontToilet	= 4, +	kHSUrinal		= 5, +	kHSScribble		= 6, +	kHSSink			= 7, +	kHSWalkArea2	= 8, +	kHSDevice		= 9, +	kHSWalkArea3	= 10, +	kHSWalkArea4	= 11, +	kHSWalkArea5	= 12, +	kHSWalkArea6	= 13, +	kHSWalkArea7	= 14, +	kHSWalkArea8	= 15, +	kHSWalkArea9	= 16 +}; + +enum { +	kASLeaveScene		= 0, +	kASBackToilet		= 1, +	kASFrontToilet		= 2, +	kASLookScribble		= 6, +	kASGrabSink			= 7, +	kASGrabSinkDone		= 8, +	kASWait				= 12, +	kASGrabUrinal		= 13 +}; + +int GnapEngine::scene13_init() { +	playSound(0x108EC, 0); +	return 0xAC; +} + +void GnapEngine::scene13_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitBar, 113, 160, 170, 455, SF_EXIT_L_CURSOR); +	setHotspot(kHSBackToilet, 385, 195, 478, 367, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSFrontToilet, 497, 182, 545, 432, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSUrinal, 680, 265, 760, 445, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSScribble, 560, 270, 660, 370, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSSink, 310, 520, 560, 599, SF_WALKABLE | SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSWalkArea1, 268, 270, 325, 385); +	setHotspot(kHSWalkArea2, 0, 0, 52, 599); +	setHotspot(kHSWalkArea3, 0, 0, 113, 550); +	setHotspot(kHSWalkArea4, 0, 0, 226, 438); +	setHotspot(kHSWalkArea5, 0, 0, 268, 400); +	setHotspot(kHSWalkArea6, 0, 0, 799, 367); +	setHotspot(kHSWalkArea7, 478, 0, 799, 401); +	setHotspot(kHSWalkArea8, 545, 0, 799, 473); +	setHotspot(kHSWalkArea9, 0, 549, 799, 599); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 17; +} + +void GnapEngine::scene13_showScribble() { +	hideCursor(); +	_largeSprite = _gameSys->createSurface(0x6F); +	_gameSys->insertSpriteDrawItem(_largeSprite, 0, 0, 300); +	while (!_mouseClickState.left && !isKeyStatus1(Common::KEYCODE_ESCAPE) && +		!isKeyStatus1(Common::KEYCODE_SPACE) && !isKeyStatus1(29)) +		gameUpdateTick(); +	_mouseClickState.left = false; +	clearKeyStatus1(Common::KEYCODE_ESCAPE); +	clearKeyStatus1(29); +	clearKeyStatus1(Common::KEYCODE_SPACE); +	_gameSys->removeSpriteDrawItem(_largeSprite, 300); +	deleteSurface(&_largeSprite); +	showCursor(); +} + +void GnapEngine::scene13_run() { +	int currSoundId = 0; + +	queueInsertDeviceIcon(); +	 +	_gameSys->insertSequence(0xAA, 256, 0, 0, kSeqNone, 0, 0, 0); +	 +	if (_prevSceneNum == 14) { +		initGnapPos(6, 6, 3); +		initBeaverPos(9, 8, 0); +	} else { +		initGnapPos(3, 7, 1); +		initBeaverPos(2, 7, 0); +	} + +	endSceneInit(); + +	_timers[4] = getRandom(20) + 20; +	_timers[5] = getRandom(50) + 50; + +	while (!_sceneDone) { +	 +		if (!isSoundPlaying(0x1091A)) +			playSound(0x1091A, 1); +	 +		testWalk(0, 0, -1, -1, -1, -1); +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene13_updateHotspots(); +				_timers[4] = getRandom(20) + 20; +				_timers[5] = getRandom(50) + 50; +			} +			break; + +		case kHSPlatypus: +			switch (_verbCursor) { +			case LOOK_CURSOR: +				playGnapMoan1(_platX, _platY); +				break; +			case GRAB_CURSOR: +				gnapKissPlatypus(0); +				break; +			case TALK_CURSOR: +				playGnapBrainPulsating(_platX, _platY); +				playBeaverSequence(getBeaverSequenceId(0, 0, 0)); +				break; +			case PLAT_CURSOR: +				break; +			} +			break; + +		case kHSExitBar: +			_isLeavingScene = 1; +			gnapWalkTo(2, 7, 0, 0x107C0, 1); +			_gnapActionStatus = kASLeaveScene; +			platypusWalkTo(2, 8, -1, -1, 1); +			if (isFlag(14) || isFlag(15)) { +				_newSceneNum = 11; +			} else { +				setFlag(15); +				_newSceneNum = 47; +			} +			break; + +		case kHSBackToilet: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapShowCurrItem(5, 5, 6, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +				case GRAB_CURSOR: +				case TALK_CURSOR: +					if (_gnapX == 5 && _gnapY == 5) { +						_s13_backToiletCtr = MIN(5, _s13_backToiletCtr + 1); +						_gameSys->setAnimation(_s13_backToiletCtr + 0xA3, _gnapId, 0); +						_gameSys->insertSequence(_s13_backToiletCtr + 0xA3, _gnapId, +							makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +							9, 0, 0, 0); +						_gnapActionStatus = kASWait; +						_gnapSequenceId = _s13_backToiletCtr + 0xA3; +						_gnapIdleFacing = 7; +						_gnapSequenceDatNum = 0; +					} else { +						gnapWalkTo(5, 5, 0, 0x107BB, 1); +						_gnapActionStatus = kASBackToilet; +						_gnapIdleFacing = 7; +					} +					break; +				case PLAT_CURSOR: +					playGnapImpossible(0, 0); +					break; +				} +			} +			break; + +		case kHSFrontToilet: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapShowCurrItem(6, 7, 7, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +				case GRAB_CURSOR: +				case TALK_CURSOR: +				case PLAT_CURSOR: +					gnapWalkTo(6, 7, 0, 0xA9, 5); +					_gnapActionStatus = kASFrontToilet; +					_gnapIdleFacing = 1; +					break; +				} +			} +			break; + +		case kHSScribble: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapShowCurrItem(7, 7, 8, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					gnapWalkTo(7, 7, 0, 0x107BB, 1); +					_gnapActionStatus = kASLookScribble; +					_gnapIdleFacing = 7; +					break; +				case GRAB_CURSOR: +					playGnapScratchingHead(0, 0); +					break; +				case TALK_CURSOR: +					_gnapIdleFacing = 7; +					gnapWalkTo(7, 7, -1, getGnapSequenceId(gskBrainPulsating, 0, 0), 1); +					break; +				case PLAT_CURSOR: +					playGnapImpossible(0, 0); +					break; +				} +			} +			break; + +		case kHSUrinal: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapShowCurrItem(8, 7, 9, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playGnapSequence(getGnapSequenceId(gskDeflect, 9, 6)); +					gnapWalkTo(_gnapX, _gnapY, 0, -1, 1); +					_gnapActionStatus = kASWait; +					break; +				case GRAB_CURSOR: +					gnapWalkTo(8, 7, 0, -1, 1); +					_gnapActionStatus = kASGrabUrinal; +					break; +				case TALK_CURSOR: +				case PLAT_CURSOR: +					playGnapImpossible(0, 0); +					break; +				} +			} +			break; + +		case kHSSink: +			if (_grabCursorSpriteIndex >= 0) { +				playGnapImpossible(0, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playGnapSequence(getGnapSequenceId(gskDeflect, 5, 9)); +					gnapWalkTo(_gnapX, _gnapY, 0, -1, 1); +					_gnapActionStatus = kASWait; +					break; +				case GRAB_CURSOR: +					gnapWalkTo(4, 8, 0, 0x107B9, 1); +					_gnapActionStatus = kASGrabSink; +					break; +				case TALK_CURSOR: +				case PLAT_CURSOR: +					playGnapImpossible(0, 0); +					break; +				} +			} +			break; + +		case kHSWalkArea2: +		case kHSWalkArea3: +		case kHSWalkArea4: +		case kHSWalkArea5: +		case kHSWalkArea6: +		case kHSWalkArea7: +		case kHSWalkArea8: +		case kHSWalkArea9: +			gnapWalkTo(-1, -1, -1, -1, 1); +			break; + +		case kHSWalkArea1: +			// Nothing +			break; +			 +		default: +			if (_mouseClickState.left) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; + +		} +	 +		scene13_updateAnimations(); +	 +		if (!_isLeavingScene) { +			updateBeaverIdleSequence(); +			if (_platY == 5 || _platY == 6) +				platypusWalkTo(-1, 7, -1, -1, 1); +			if (_gnapActionStatus < 0) +				updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = getRandom(20) + 20; +				_gnapRandomValue = getRandom(5); +				switch (_gnapRandomValue) { +				case 0: +					playSound(0xD2, 0); +					break; +				case 1: +					playSound(0xD3, 0); +					break; +				case 2: +					playSound(0xD4, 0); +					break; +				case 3: +					playSound(0xD5, 0); +					break; +				case 4: +					playSound(0xD6, 0); +					break; +				} +			} +			if (!_timers[5]) { +				int newSoundId; +				_timers[5] = getRandom(50) + 50; +				_gnapRandomValue = getRandom(7); +				switch (_gnapRandomValue) { +				case 0: +					newSoundId = 0xD7; +					_timers[5] = 2 * getRandom(50) + 100; +					break; +				case 1: +				case 2: +					newSoundId = 0xCF; +					break; +				case 3: +				case 4: +					newSoundId = 0xD0; +					break; +				default: +					newSoundId = 0xD1; +					break; +				} +				if (newSoundId != currSoundId) { +					playSound(newSoundId, 0); +					currSoundId = newSoundId; +				} +			} +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene13_updateHotspots(); +			_timers[4] = getRandom(20) + 20; +			_timers[5] = getRandom(50) + 50; +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene13_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASLeaveScene: +			_sceneDone = true; +			_gnapActionStatus = -1; +			break; +		case kASBackToilet: +			_s13_backToiletCtr = MIN(5, _s13_backToiletCtr + 1); +			_gameSys->insertSequence(_s13_backToiletCtr + 0xA3, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 9, 0, 0, 0); +			_gnapSequenceId = _s13_backToiletCtr + 0xA3; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = -1; +			break; +		case kASFrontToilet: +			_sceneDone = true; +			_newSceneNum = 14; +			break; +		case kASLookScribble: +			_gnapActionStatus = -1; +			scene13_showScribble(); +			break; +		case kASGrabSink: +			_gameSys->setAnimation(0xAB, 160, 0); +			_gameSys->insertSequence(0xAB, 160, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->removeSequence(0xAA, 256, 1); +			_gnapSequenceId = 0xAB; +			_gnapId = 160; +			_gnapIdleFacing = 1; +			_gnapSequenceDatNum = 0; +			_gnapX = 4; +			_gnapY = 8; +			_timers[2] = 360; +			_gnapActionStatus = kASGrabSinkDone; +			break; +		case kASGrabSinkDone: +			_gameSys->insertSequence(0xAA, 256, 0, 0, kSeqNone, 0, 0, 0); +			_gnapActionStatus = -1; +			break; +		case kASWait: +			_gnapActionStatus = -1; +			break; +		case kASGrabUrinal: +			_gameSys->setAnimation(0xA2, 120, 0); +			_gameSys->insertSequence(0xA2, 120, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0xA2; +			_gnapId = 120; +			_gnapIdleFacing = 3; +			_gnapSequenceDatNum = 0; +			_gnapX = 4; +			_gnapY = 6; +			_timers[2] = 360; +			_gnapActionStatus = kASWait; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(1) == 2) { +		_gameSys->setAnimation(0, 0, 1); +		_beaverActionStatus = -1; +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene14.cpp b/engines/gnap/scenes/scene14.cpp new file mode 100644 index 0000000000..4f799db977 --- /dev/null +++ b/engines/gnap/scenes/scene14.cpp @@ -0,0 +1,194 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSExit			= 1, +	kHSCoin			= 2, +	kHSToilet		= 3, +	kHSDevice		= 4 +}; + +int GnapEngine::scene14_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	return 0x27; +} + +void GnapEngine::scene14_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0); +	setHotspot(kHSExit, 0, 590, 799, 599, SF_EXIT_D_CURSOR); +	setHotspot(kHSCoin, 330, 390, 375, 440, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSToilet, 225, 250, 510, 500, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	if (isFlag(2)) +		_hotspots[kHSCoin].flags = SF_DISABLED; +	_hotspotsCount = 5; +} + +void GnapEngine::scene14_run() { + +	_largeSprite = 0; + +	queueInsertDeviceIcon(); +	 +	if (!isFlag(2)) +		_gameSys->insertSequence(0x23, 10, 0, 0, kSeqNone, 0, 0, 0); +	 +	endSceneInit(); +	 +	if (!isFlag(2) && invHas(kItemTongs)) +		_largeSprite = _gameSys->createSurface(1); + +	if (!isFlag(2)) { +		_gameSys->insertSequence(0x24, 10, 0x23, 10, kSeqSyncWait, 0, 0, 0); +		_gnapSequenceId = 0x24; +		_timers[2] = getRandom(40) + 50; +	} +	 +	while (!_sceneDone) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene14_updateHotspots(); +			} +			break; + +		case kHSExit: +			_sceneDone = true; +			_newSceneNum = 13; +			break; + +		case kHSCoin: +			if (_grabCursorSpriteIndex == kItemTongs) { +				invAdd(kItemQuarter); +				setFlag(2); +				setGrabCursorSprite(-1); +				hideCursor(); +				_gameSys->setAnimation(0x26, 10, 0); +				_gameSys->insertSequence(0x26, 10, _gnapSequenceId, 10, kSeqSyncWait, 0, 0, 0); +			} else if (_grabCursorSpriteIndex >= 0) { +				playSound(0x108E9, 0); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playSound(0x108E9, 0); +					break; +				case GRAB_CURSOR: +					_gameSys->insertSequence(0x25, 10, _gnapSequenceId, 10, kSeqSyncWait, 0, 0, 0); +					_gameSys->insertSequence(0x23, 10, 0x25, 10, kSeqSyncWait, 0, 0, 0); +					_gnapSequenceId = 0x23; +					break; +				case TALK_CURSOR: +					playSound((getRandom(5) + 0x8D5) | 0x10000, 0); +					break; +				case PLAT_CURSOR: +					_gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY); +					break; +				} +			} +			break; + +		case kHSToilet: +			if (_grabCursorSpriteIndex >= 0) { +				_gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +				case GRAB_CURSOR: +					playSound(0x108B1, 0); +					break; +				case TALK_CURSOR: +					playSound((getRandom(5) + 0x8D5) | 0x10000, 0); +					break; +				case PLAT_CURSOR: +					_gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY); +					break; +				} +			} +			break; + +		default: +			_mouseClickState.left = false; +			break; + +		} +	 +		scene14_updateAnimations(); +	 +		checkGameKeys(); +	 +		if (!isFlag(2) && !_timers[2]) { +			_gameSys->insertSequence(0x24, 10, _gnapSequenceId, 10, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x24; +			_timers[2] = getRandom(40) + 50; +		} +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene14_updateHotspots(); +		} +		 +		gameUpdateTick(); + +	} +	 +	if (_largeSprite) +		deleteSurface(&_largeSprite); + +} + +void GnapEngine::scene14_updateAnimations() { +	 +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		_gameSys->insertSpriteDrawItem(_largeSprite, 0, 0, 300); +		_gameSys->setAnimation(0x10843, 301, 1); +		_gameSys->insertSequence(0x10843, 301, 0x26, 10, kSeqSyncWait, 0, 0, 0); +	} +	 +	if (_gameSys->getAnimationStatus(1) == 2) { +		_gameSys->setAnimation(0, 0, 1); +		_sceneDone = true; +		_newSceneNum = 13; +		_grabCursorSpriteIndex = kItemQuarter; +	} +	 +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene15.cpp b/engines/gnap/scenes/scene15.cpp new file mode 100644 index 0000000000..54eb146fa5 --- /dev/null +++ b/engines/gnap/scenes/scene15.cpp @@ -0,0 +1,343 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSExit			= 1, +	kHSButton1		= 2, +	kHSButton2		= 3, +	kHSButton3		= 4, +	kHSButton4		= 5, +	kHSButton5		= 6, +	kHSButton6		= 7, +	kHSButtonA		= 8, +	kHSButtonB		= 9, +	kHSButtonC		= 10, +	kHSButtonD		= 11, +	kHSButtonE		= 12, +	kHSButtonF		= 13, +	kHSCoinSlot		= 14, +	kHSPlayButton	= 15, +	kHSDevice		= 16 +}; + +int GnapEngine::scene15_init() { +	return 0xDD; +} + +void GnapEngine::scene15_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED); +	setHotspot(kHSExit, 50, 590, 750, 599, SF_EXIT_D_CURSOR); +	setHotspot(kHSButton1, 210, 425, 260, 475, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSButton2, 280, 425, 325, 475, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSButton3, 340, 425, 385, 475, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSButton4, 400, 425, 445, 475, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSButton5, 460, 425, 510, 475, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSButton6, 520, 425, 560, 475, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSButtonA, 205, 480, 250, 535, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSButtonB, 270, 480, 320, 535, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSButtonC, 335, 480, 380, 535, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSButtonD, 395, 480, 445, 535, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSButtonE, 460, 480, 505, 535, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSButtonF, 515, 480, 560, 535, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSCoinSlot, 585, 475, 620, 535, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSPlayButton, 622, 431, 650, 482, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 17; +} + +void GnapEngine::scene15_run() { +	 +	_s15_currSlotSequenceId = -1; +	_s15_currUpperButtonSequenceId = -1; +	_s15_currLowerButtonSequenceId = -1; +	_s15_nextSlotSequenceId = -1; +	_s15_nextUpperButtonSequenceId = -1; +	_s15_nextLowerButtonSequenceId = -1; +	_s15_currRecordSequenceId = 0xD5; +	_s15_nextRecordSequenceId = -1; + +	_gameSys->setAnimation(0xD5, 1, 0); +	_gameSys->insertSequence(_s15_currRecordSequenceId, 1, 0, 0, kSeqNone, 0, 0, 0); +	 +	queueInsertDeviceIcon(); +	 +	endSceneInit(); +	 +	while (!_sceneDone) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		_hotspots[kHSPlatypus].x1 = 0; +		_hotspots[kHSPlatypus].y1 = 0; +		_hotspots[kHSPlatypus].x2 = 0; +		_hotspots[kHSPlatypus].y2 = 0; +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +		 +		if (_sceneClickedHotspot >= 0) +			debug("_sceneClickedHotspot: %d; _verbCursor: %d", _sceneClickedHotspot, _verbCursor); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene15_updateHotspots(); +			} +			break; + +		case kHSExit: +			_newSceneNum = 12; +			_isLeavingScene = true; +			break; + +		case kHSCoinSlot: +			if (_grabCursorSpriteIndex == kItemQuarter || _grabCursorSpriteIndex == kItemQuarterWithHole) { +				_s15_nextSlotSequenceId = 0xDC; // Insert coin +			} else if (_grabCursorSpriteIndex == kItemDiceQuarterHole) { +				_s15_nextSlotSequenceId = 0xDB; +			} else if (_grabCursorSpriteIndex >= 0) { +				_gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +				case GRAB_CURSOR: +					playSound(0x108E9, 0); +					break; +				case TALK_CURSOR: +					playSound((getRandom(5) + 0x8D5) | 0x10000, 0); +					break; +				case PLAT_CURSOR: +					_gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY); +					break; +				} +			} +			break; + +		case kHSPlayButton: +			if (_grabCursorSpriteIndex >= 0) { +				_gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					if (isFlag(12) || isFlag(13)) +						playSound(0x108E9, 0); +					else +						_s15_nextSlotSequenceId = 0xDA; +					break; +				case GRAB_CURSOR: +					if (isFlag(12) || isFlag(13)) +						_s15_nextSlotSequenceId = 0xD9; +					else +						_s15_nextSlotSequenceId = 0xDA; +					break; +				case TALK_CURSOR: +					playSound((getRandom(5) + 0x8D5) | 0x10000, 0); +					break; +				case PLAT_CURSOR: +					_gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY); +					break; +				} +			} +			break; + +		case kHSButton1: +		case kHSButton2: +		case kHSButton3: +		case kHSButton4: +		case kHSButton5: +		case kHSButton6: +			if (_grabCursorSpriteIndex >= 0) { +				_gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playSound(0x108E9, 0); +					break; +				case GRAB_CURSOR: +					_s15_nextUpperButtonSequenceId = _sceneClickedHotspot + 0xC5; +					break; +				case TALK_CURSOR: +					playSound((getRandom(5) + 0x8D5) | 0x10000, 0); +					break; +				case PLAT_CURSOR: +					_gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY); +					break; +				} +			} +			break; + +		case kHSButtonA: +		case kHSButtonB: +		case kHSButtonC: +		case kHSButtonD: +		case kHSButtonE: +		case kHSButtonF: +			if (_grabCursorSpriteIndex >= 0) { +				_gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playSound(0x108E9, 0); +					break; +				case GRAB_CURSOR: +					_s15_nextLowerButtonSequenceId = _sceneClickedHotspot + 0xC5; +					break; +				case TALK_CURSOR: +					playSound((getRandom(5) + 0x8D5) | 0x10000, 0); +					break; +				case PLAT_CURSOR: +					_gameSys->insertSequence(0x107A8, 1, 0, 0, kSeqNone, 0, 900 - _gnapGridX, 576 - _gnapGridY); +					break; +				} +			} +			break; + +		default: +			_mouseClickState.left = false; +			break; + +		} +	 +		scene15_updateAnimations(); +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene15_updateHotspots(); +		} +		 +		gameUpdateTick(); +		 +	} + +} + +void GnapEngine::scene15_updateAnimations() { +	 +	if (_gameSys->getAnimationStatus(0) == 2) { +		if (_isLeavingScene) { +			_sceneDone = true; +		} else if (_s15_nextSlotSequenceId != -1) { +			_gameSys->setAnimation(_s15_nextSlotSequenceId, 1, 0); +			_gameSys->insertSequence(_s15_nextSlotSequenceId, 1, 0, 0, kSeqNone, 0, 0, 0); +			_s15_currSlotSequenceId = _s15_nextSlotSequenceId; +			_s15_nextSlotSequenceId = -1; +			switch (_s15_currSlotSequenceId) { +			case 0xDC: +				if (_grabCursorSpriteIndex == kItemQuarter) { +					invRemove(kItemQuarter); +				} else { +					invRemove(kItemQuarterWithHole); +					setFlag(13); +				} +				setGrabCursorSprite(-1); +				break; +			case 0xDB: +				setFlag(14); +				setGrabCursorSprite(-1); +				_s15_nextSlotSequenceId = 0xD8; +				break; +			case 0xD9: +				if (isFlag(12)) { +					clearFlag(12); +					invAdd(kItemQuarter); +					_newGrabCursorSpriteIndex = kItemQuarter; +				} else if (isFlag(13)) { +					clearFlag(13); +					invAdd(kItemQuarterWithHole); +					_newGrabCursorSpriteIndex = kItemQuarterWithHole; +				} +				_newSceneNum = 12; +				_isLeavingScene = true; +				break; +			case 0xD8: +			case 0xDA: +				if (_s15_currUpperButtonSequenceId != -1) { +					_gameSys->removeSequence(_s15_currUpperButtonSequenceId, 1, 1); +					_s15_currUpperButtonSequenceId = -1; +				} +				if (_s15_currLowerButtonSequenceId != -1) { +					_gameSys->removeSequence(_s15_currLowerButtonSequenceId, 1, 1); +					_s15_currLowerButtonSequenceId = -1; +				} +				break; +			} +		} else if (_s15_nextRecordSequenceId != -1) { +			_gameSys->setAnimation(_s15_nextRecordSequenceId, 1, 0); +			_gameSys->insertSequence(_s15_nextRecordSequenceId, 1, _s15_currRecordSequenceId, 1, kSeqSyncWait, 0, 0, 0); +			_s15_currRecordSequenceId = _s15_nextRecordSequenceId; +			_s15_nextRecordSequenceId = -1; +			if (_s15_currRecordSequenceId == 0xD3) { +				invRemove(kItemDiceQuarterHole); +				_newSceneNum = 16; +				_isLeavingScene = true; +			} +			_gameSys->removeSequence(_s15_currUpperButtonSequenceId, 1, 1); +			_s15_currUpperButtonSequenceId = -1; +			_gameSys->removeSequence(_s15_currLowerButtonSequenceId, 1, 1); +			_s15_currLowerButtonSequenceId = -1; +		} else if (_s15_nextUpperButtonSequenceId != -1) { +			_gameSys->setAnimation(_s15_nextUpperButtonSequenceId, 1, 0); +			if (_s15_currUpperButtonSequenceId == -1) +				_gameSys->insertSequence(_s15_nextUpperButtonSequenceId, 1, 0, 0, kSeqNone, 0, 0, 0); +			else +				_gameSys->insertSequence(_s15_nextUpperButtonSequenceId, 1, _s15_currUpperButtonSequenceId, 1, kSeqSyncWait, 0, 0, 0); +			_s15_currUpperButtonSequenceId = _s15_nextUpperButtonSequenceId; +			_s15_nextUpperButtonSequenceId = -1; +			if (_s15_currLowerButtonSequenceId != -1 && isFlag(14)) { +				if (_s15_currUpperButtonSequenceId == 0xCC && _s15_currLowerButtonSequenceId == 0xCE) +					_s15_nextRecordSequenceId = 0xD3; +				else +					_s15_nextRecordSequenceId = 0xD4; +			} +		} else if (_s15_nextLowerButtonSequenceId != -1) { +			_gameSys->setAnimation(_s15_nextLowerButtonSequenceId, 1, 0); +			if (_s15_currLowerButtonSequenceId == -1) +				_gameSys->insertSequence(_s15_nextLowerButtonSequenceId, 1, 0, 0, kSeqNone, 0, 0, 0); +			else +				_gameSys->insertSequence(_s15_nextLowerButtonSequenceId, 1, _s15_currLowerButtonSequenceId, 1, kSeqSyncWait, 0, 0, 0); +			_s15_currLowerButtonSequenceId = _s15_nextLowerButtonSequenceId; +			_s15_nextLowerButtonSequenceId = -1; +			if (_s15_currUpperButtonSequenceId != -1 && isFlag(14)) { +				if (_s15_currUpperButtonSequenceId == 0xCC && _s15_currLowerButtonSequenceId == 0xCE) +					_s15_nextRecordSequenceId = 0xD3; +				else +					_s15_nextRecordSequenceId = 0xD4; +			} +		} +	} +	 +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene16.cpp b/engines/gnap/scenes/scene16.cpp new file mode 100644 index 0000000000..dfc852293e --- /dev/null +++ b/engines/gnap/scenes/scene16.cpp @@ -0,0 +1,82 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +void GnapEngine::scene16_initCutscene() { +	_s99_dword_47F370[0] = 0x1F2; +	_s99_dword_47F370[1] = 0x201; +	_s99_dword_47F370[2] = 0x1FC; +	_s99_dword_47F370[3] = 0x1F4; +	_s99_dword_47F370[4] = 0x1FB; +	_s99_dword_47F370[5] = 0x1F0; +	_s99_dword_47F370[6] = 0x1FD; +	_s99_dword_47F370[7] = 0x1FE; +	_s99_dword_47F370[8] = 0x1F7; +	_s99_dword_47F370[9] = 0x1F9; +	_s99_dword_47F370[10] = 0x1F8; +	_s99_dword_47F370[11] = 0x1F1; +	_s99_dword_47F370[12] = 0x202; +	_s99_dword_47F370[13] = 0x1F6; +	_s99_dword_47F370[14] = 0x1F3; +	_s99_dword_47F370[15] = 0x1FA; +	_s99_dword_47F370[16] = 0x1FF; +	_s99_dword_47F370[17] = 0x200; +	_s99_dword_47F370[18] = 0x203; +	_s99_dword_47F370[19] = 0x206; +	_s99_dword_47F370[20] = 0x207; +	_s99_dword_47F370[21] = 0x204; +	_s99_dword_47F370[22] = 0x205; +	_s99_dword_47F2F0[0] = 0x1C; +	_s99_dword_47F2F0[1] = 2; +	_s99_dword_47F2F0[2] = 0x1B; +	_s99_dword_47F2F0[3] = 0; +	_s99_dword_47F2F0[4] = 0x167; +	_s99_dword_47F2F0[5] = 1; +	_s99_dword_47F2F0[6] = 0x15B; +	_s99_dword_47F2F0[7] = 0x15A; +	_s99_dword_47F2F0[8] = 0x170; +	_s99_dword_47F2F0[9] = 0x1EB; +	_s99_dword_47F2F0[10] = 0x1EC; +	_s99_dword_47F2F0[11] = 0x1BE; +	_s99_dword_47F2F0[12] = 0x1BF; +	_s99_dword_47F330[0] = 4; +	_s99_dword_47F330[1] = 1; +	_s99_dword_47F330[2] = 1; +	_s99_dword_47F330[3] = 6; +	_s99_dword_47F330[4] = 1; +	_s99_dword_47F330[5] = 3; +	_s99_dword_47F330[6] = 1; +	_s99_dword_47F330[7] = 1; +	_s99_dword_47F330[8] = 1; +	_s99_dword_47F330[9] = 1; +	_s99_dword_47F330[10] = 1; +	_s99_dword_47F330[11] = 1; +	_s99_dword_47F330[12] = 1; +	_s99_itemsCount = 13; +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene17.cpp b/engines/gnap/scenes/scene17.cpp new file mode 100644 index 0000000000..5b7c54c0a8 --- /dev/null +++ b/engines/gnap/scenes/scene17.cpp @@ -0,0 +1,846 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSPhone1		= 1, +	kHSPhone2		= 2, +	kHSExitGrubCity	= 3, +	kHSDevice		= 4, +	kHSExitToyStore	= 5, +	kHSWrench		= 6, +	kHSWalkArea1	= 7, +	kHSWalkArea2	= 8, +	kHSWalkArea3	= 9 +}; + +enum { +	kASTryGetWrench				= 0, +	kASGetWrench2				= 1, +	kASGetWrenchDone			= 2, +	kASGetWrench1				= 3, +	kASPlatUsePhone				= 4, +	kASPutCoinIntoPhone			= 5, +	kASGetCoinFromPhone			= 6, +	kASGetCoinFromPhoneDone		= 7, +	kASPutCoinIntoPhoneDone		= 8, +	kASGnapUsePhone				= 9, +	kASGetWrenchGnapReady		= 10, +	kASGnapHangUpPhone			= 11, +	kASPlatPhoningAssistant		= 12, +	kASPlatHangUpPhone			= 14, +	kASLeaveScene				= 15 +}; + +int GnapEngine::scene17_init() { +	return 0x263; +} + +void GnapEngine::scene17_updateHotspots() { +	setHotspot(kHSPlatypus, 1, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSPhone1, 61, 280, 97, 322, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 1, 7); +	setHotspot(kHSPhone2, 80, 204, 178, 468, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 1, 7); +	setHotspot(kHSExitGrubCity, 196, 207, 280, 304, SF_EXIT_U_CURSOR, 3, 5); +	setHotspot(kHSExitToyStore, 567, 211, 716, 322, SF_EXIT_U_CURSOR, 5, 6); +	setHotspot(kHSWrench, 586, 455, 681, 547, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 5, 7); +	setHotspot(kHSWalkArea1, 0, 0, 800, 434); +	setHotspot(kHSWalkArea2, 541, 0, 800, 600); +	setHotspot(kHSWalkArea3, 0, 204, 173, 468); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	if (isFlag(6)) +		_hotspots[kHSWrench].flags = 0; +	if (isFlag(26)) { +		_hotspots[kHSDevice].flags = SF_DISABLED; +		_hotspots[kHSPlatypus].flags = SF_DISABLED; +	} +	_hotspotsCount = 10; +} + +void GnapEngine::scene17_update() { +	gameUpdateTick(); +	updateMouseCursor(); +	updateGrabCursorSprite(0, 0); +	if (_mouseClickState.left) { +		gnapWalkTo(-1, -1, -1, -1, 1); +		_mouseClickState.left = false; +	} +} + +void GnapEngine::scene17_platHangUpPhone() { +	int savedGnapActionStatus = _gnapActionStatus; + +	if (_beaverActionStatus == kASPlatPhoningAssistant) { +		_gnapActionStatus = kASPlatHangUpPhone; +		updateMouseCursor(); +		_s17_platPhoneCtr = 0; +		_beaverActionStatus = -1; +		_gameSys->setAnimation(0x257, 254, 4); +		_gameSys->insertSequence(0x257, 254, _s17_currPhoneSequenceId, 254, 32, 0, 0, 0); +		while (_gameSys->getAnimationStatus(4) != 2) +			gameUpdateTick(); +		_gameSys->setAnimation(0x25B, _beaverId, 1); +		_gameSys->insertSequence(0x25B, _beaverId, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0); +		_beaverSequenceId = 0x25B; +		_beaverSequenceDatNum = 0; +		_s17_currPhoneSequenceId = -1; +		_s17_nextPhoneSequenceId = -1; +		clearFlag(26); +		while (_gameSys->getAnimationStatus(1) != 2) +			gameUpdateTick(); +		_gnapActionStatus = savedGnapActionStatus; +		updateMouseCursor(); +	} +	scene17_updateHotspots(); +} + +void GnapEngine::scene17_run() { + +	playSound(0x10940, 1); +	startSoundTimerA(8); +	_sceneWaiting = false; +	_timers[4] = getRandom(100) + 200; +	_timers[3] = 200; +	_timers[5] = getRandom(30) + 80; +	_timers[6] = getRandom(30) + 200; +	_timers[7] = getRandom(100) + 100; + +	if (isFlag(9)) { +		_gameSys->insertSequence(0x25F, 20, 0, 0, kSeqNone, 0, 0, 0); +	} else { +		if (_s18_garbageCanPos >= 8) { +			_gameSys->insertSequence(0x260, 20, 0, 0, kSeqNone, 0, 97, 1); +		} else if (_s18_garbageCanPos >= 6) { +			_gameSys->insertSequence(0x260, 20, 0, 0, kSeqNone, 0, 68, 2); +		} else if (_s18_garbageCanPos >= 5) { +			_gameSys->insertSequence(0x260, 20, 0, 0, kSeqNone, 0, 23, -1); +		} else if (_s18_garbageCanPos >= 4) { +			_gameSys->insertSequence(0x260, 20, 0, 0, kSeqNone, 0, -11, -5); +		} else { +			_gameSys->insertSequence(0x260, 20, 0, 0, kSeqNone, 0, -54, -8); +		} +	} + +	if (isFlag(19)) +		_gameSys->insertSequence(0x262, 1, 0, 0, kSeqNone, 0, 0, 0); + +	queueInsertDeviceIcon(); + +	if (isFlag(6)) +		_s17_currWrenchSequenceId = 0x22D; +	else +		_s17_currWrenchSequenceId = 0x22F; + +	_s17_currCarWindowSequenceId = 0x244; + +	if (isFlag(14)) +		_gameSys->insertSequence(0x261, 1, 0, 0, kSeqNone, 0, 0, 0); + +	_gameSys->setAnimation(_s17_currWrenchSequenceId, 40, 2); +	_gameSys->insertSequence(_s17_currWrenchSequenceId, 40, 0, 0, kSeqNone, 0, 0, 0); + +	if (isFlag(6)) { +		_gameSys->setAnimation(0, 0, 3); +	} else { +		_gameSys->setAnimation(_s17_currCarWindowSequenceId, 40, 3); +		_gameSys->insertSequence(_s17_currCarWindowSequenceId, 40, 0, 0, kSeqNone, 0, 0, 0); +	} + +	_s17_canTryGetWrench = true; + +	if (isFlag(18)) +		_gameSys->insertSequence(0x24F, 100, 0, 0, kSeqNone, 0, 0, 0); + +	if (_prevSceneNum == 53 || _prevSceneNum == 18 || _prevSceneNum == 20 || _prevSceneNum == 19) { +		if (_prevSceneNum == 20) { +			initGnapPos(4, 6, 1); +			initBeaverPos(5, 6, 0); +			endSceneInit(); +			platypusWalkTo(5, 9, -1, 0x107C2, 1); +			gnapWalkTo(4, 8, -1, 0x107B9, 1); +		} else if (isFlag(27)) { +			initGnapPos(3, 9, 5); +			_platX = _hotspotsWalkPos[2].x; +			_platY = _hotspotsWalkPos[2].y; +			_beaverId = 20 * _hotspotsWalkPos[2].y; +			_gameSys->insertSequence(0x25A, 20 * _hotspotsWalkPos[2].y, 0, 0, kSeqNone, 0, 0, 0); +			_gameSys->insertSequence(0x257, 254, 0, 0, kSeqNone, 0, 0, 0); +			_beaverSequenceId = 0x25A; +			_beaverSequenceDatNum = 0; +			endSceneInit(); +			clearFlag(15); +			clearFlag(16); +			_beaverActionStatus = kASPlatPhoningAssistant; +			scene17_platHangUpPhone(); +			_gameSys->setAnimation(0, 0, 4); +			clearFlag(26); +			clearFlag(27); +			scene17_updateHotspots(); +		} else if (isFlag(25)) { +			clearFlag(15); +			clearFlag(16); +			initBeaverPos(7, 9, 0); +			_gnapX = _hotspotsWalkPos[2].x; +			_gnapY = _hotspotsWalkPos[2].y; +			_gnapId = 20 * _hotspotsWalkPos[2].y; +			_gameSys->insertSequence(601, 20 * _hotspotsWalkPos[2].y, 0, 0, kSeqNone, 0, 0, 0); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 601; +			_gnapActionStatus = kASGnapHangUpPhone; +			clearFlag(25); +			_gameSys->insertSequence(0x251, 254, 0, 0, kSeqNone, 0, 0, 0); +			endSceneInit(); +			_gameSys->setAnimation(0x257, 254, 0); +			_gameSys->insertSequence(0x257, 254, 0x251, 254, kSeqSyncWait, 0, 0, 0); +		} else if (isFlag(26)) { +			clearFlag(15); +			clearFlag(16); +			_sceneWaiting = true; +			initGnapPos(3, 9, 5); +			_platX = _hotspotsWalkPos[2].x; +			_platY = _hotspotsWalkPos[2].y; +			_beaverId = 20 * _hotspotsWalkPos[2].y; +			_s17_currPhoneSequenceId = 0x251; +			_gameSys->insertSequence(0x25A, 20 * _hotspotsWalkPos[2].y, 0, 0, kSeqNone, 0, 0, 0); +			_gameSys->insertSequence(_s17_currPhoneSequenceId, 254, 0, 0, kSeqNone, 0, 0, 0); +			_beaverSequenceId = 0x25A; +			_beaverSequenceDatNum = 0; +			endSceneInit(); +			_gameSys->setAnimation(_s17_currPhoneSequenceId, 254, 1); +			_beaverActionStatus = kASPlatPhoningAssistant; +			scene17_updateHotspots(); +		} else if (_prevSceneNum == 18) { +			initGnapPos(6, 6, 1); +			initBeaverPos(5, 6, 0); +			endSceneInit(); +			platypusWalkTo(5, 9, -1, 0x107C2, 1); +			gnapWalkTo(4, 8, -1, 0x107B9, 1); +		} else { +			if (isFlag(15)) { +				initGnapPos(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 1); +				initBeaverPos(1, 9, 0); +				endSceneInit(); +			} else { +				initGnapPos(3, 7, 1); +				initBeaverPos(1, 7, 0); +				endSceneInit(); +			} +			clearFlag(15); +			clearFlag(16); +			endSceneInit(); +		} +	} else { +		_gnapX = 3; +		_gnapY = 6; +		_gnapId = 120; +		_gnapSequenceId = 0x23D; +		_gnapSequenceDatNum = 0; +		_gnapIdleFacing = 1; +		_gameSys->insertSequence(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0, 0, kSeqNone, 0, 0, 0); +		_platX = -1; +		_platY = 8; +		_beaverId = 160; +		_gameSys->insertSequence(0x241, 160, 0, 0, kSeqNone, 0, 0, 0); +		_gameSys->insertSequence(0x107C1, _beaverId, 0x241, _beaverId, +			9, 0, 75 * _platX - _platGridX, 48 * _platY - _platGridY); +		_gameSys->insertSequence(0x22C, 2, 0, 0, kSeqNone, 0, 0, 0); +		// TODO delayTicksA(2, 9); +		endSceneInit(); +		_beaverSequenceId = 0x7C1; +		_beaverSequenceDatNum = 1; +		_beaverFacing = 1; +		platypusWalkTo(2, 9, -1, 0x107C2, 1); +	} + +	while (!_sceneDone) { + +		updateMouseCursor(); +		updateCursorByHotspot(); + +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0 || _gnapActionStatus == 3) { +				runMenu(); +				scene17_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemJoint) { +					if (isFlag(6)) { +						gnapUseJointOnPlatypus(); +					} else { +						gnapUseDeviceOnBeaver(); +						platypusWalkTo(_hotspotsWalkPos[6].x, _hotspotsWalkPos[6].y, 1, 0x107C2, 1); +						gnapWalkTo(_hotspotsWalkPos[6].x + 1, _hotspotsWalkPos[6].y, 0, 0x107BA, 1); +						_beaverActionStatus = kASGetWrench1; +						_gnapActionStatus = kASGetWrench1; +						_timers[5] = getRandom(30) + 80; +						setGrabCursorSprite(-1); +						invRemove(kItemJoint); +					} +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapScratchingHead(_platX, _platY); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +					case GRAB_CURSOR: +						playGnapScratchingHead(_platX, _platY); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSWrench: +			if (_gnapActionStatus < 0) { +				if (isFlag(6)) { +					playGnapImpossible(0, 0); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 8, 7); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +					case GRAB_CURSOR: +						playGnapScratchingHead(8, 7); +						break; +					case TALK_CURSOR: +						playGnapImpossible(0, 0); +						break; +					case PLAT_CURSOR: +						if (_s17_canTryGetWrench) { +							scene17_platHangUpPhone(); +							gnapUseDeviceOnBeaver(); +							platypusWalkTo(_hotspotsWalkPos[6].x + 1, _hotspotsWalkPos[6].y, 1, 0x107C2, 1); +							_beaverActionStatus = kASTryGetWrench; +							_gnapActionStatus = kASTryGetWrench; +							_timers[5] = getRandom(30) + 80; +						} else +							playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +	 +		case kHSPhone1: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemDiceQuarterHole) { +					gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +					_gnapActionStatus = kASPutCoinIntoPhone; +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 1, 3); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(1, 3); +						break; +					case GRAB_CURSOR: +						if (isFlag(18)) { +							scene17_platHangUpPhone(); +							gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, _hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y) | 0x10000, 1); +							_gnapActionStatus = kASGetCoinFromPhone; +						} else +							playGnapImpossible(0, 0); +						break; +					case TALK_CURSOR: +						playGnapImpossible(0, 0); +						break; +					case PLAT_CURSOR: +						if (isFlag(18)) { +							scene17_platHangUpPhone(); +							_isLeavingScene = true; +							gnapUseDeviceOnBeaver(); +							_beaverFacing = 5; +							platypusWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 1, 0x107C2, 1); +							setFlag(16); +							_beaverActionStatus = kASPlatUsePhone; +							_gnapActionStatus = kASPlatUsePhone; +						} else +							playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSPhone2: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemDiceQuarterHole) { +					gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +					_gnapActionStatus = kASPutCoinIntoPhone; +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 1, 3); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(1, 3); +						break; +					case GRAB_CURSOR: +						if (isFlag(18)) { +							scene17_platHangUpPhone(); +							_isLeavingScene = true; +							_gnapIdleFacing = 5; +							gnapWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +							_gnapActionStatus = kASGnapUsePhone; +							setFlag(15); +						} else +							playGnapImpossible(0, 0); +						break; +					case TALK_CURSOR: +						playGnapImpossible(0, 0); +						break; +					case PLAT_CURSOR: +						if (isFlag(18)) { +							scene17_platHangUpPhone(); +							_isLeavingScene = true; +							gnapUseDeviceOnBeaver(); +							_beaverFacing = 5; +							platypusWalkTo(_hotspotsWalkPos[2].x, _hotspotsWalkPos[2].y, 1, 0x107C2, 1); +							setFlag(16); +							_beaverActionStatus = kASPlatUsePhone; +							_gnapActionStatus = kASPlatUsePhone; +						} else +							playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +	 +		case kHSExitToyStore: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				_newSceneNum = 18; +				_gnapIdleFacing = 7; +				gnapWalkTo(_hotspotsWalkPos[5].x, _hotspotsWalkPos[5].y, 0, 0x107BB, 1); +				_gnapActionStatus = kASLeaveScene; +				if (_beaverActionStatus != kASPlatPhoningAssistant) +					platypusWalkTo(_hotspotsWalkPos[5].x - 1, _hotspotsWalkPos[5].y, -1, 0x107C2, 1); +			} +			break; +	 +		case kHSExitGrubCity: +			if (_gnapActionStatus < 0) { +				scene17_platHangUpPhone(); +				_isLeavingScene = true; +				_newSceneNum = 20; +				_gnapIdleFacing = 5; +				gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, 0, 0x107BC, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[3].x + 1, _hotspotsWalkPos[3].y, -1, 0x107C2, 1); +			} +			break; +	 +		case kHSWalkArea1: +		case kHSWalkArea2: +		case kHSWalkArea3: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; +	 +		default: +			if (_mouseClickState.left && _gnapActionStatus < 0) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = 0; +			} +			break; +		} +	 +		scene17_updateAnimations(); +		 +		if (!isSoundPlaying(0x10940)) +			playSound(0x10940, 1); +	 +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0) +				beaverSub426234(); +			updateGnapIdleSequence2(); +			if (!_timers[4]) { +				_timers[4] = getRandom(100) + 200; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0) +					_gameSys->insertSequence(0x22B, 21, 0, 0, kSeqNone, 0, 0, 0); +			} +			if (!_timers[7]) { +				_timers[7] = getRandom(100) + 100; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0) { +					switch (getRandom(3)) { +					case 0: +						_gameSys->insertSequence(0x25C, 255, 0, 0, kSeqNone, 0, 0, 0); +						break; +					case 1: +						_gameSys->insertSequence(0x25D, 255, 0, 0, kSeqNone, 0, 0, 0); +						break; +					case 2: +						_gameSys->insertSequence(0x25E, 255, 0, 0, kSeqNone, 0, 0, 0); +						break; +					} +				} +			} +			if (_beaverActionStatus < 0 && !_timers[5]) { +				_timers[5] = getRandom(30) + 80; +				if (isFlag(6) && _s17_nextWrenchSequenceId == -1) { +					_s17_nextWrenchSequenceId = 0x236; +				} else if (_s17_canTryGetWrench) { +					switch (getRandom(6)) { +					case 0: +						_s17_nextWrenchSequenceId = 0x231; +						break; +					case 1: +						_s17_nextWrenchSequenceId = 0x232; +						break; +					case 2: +					case 3: +						_s17_nextWrenchSequenceId = 0x23C; +						break; +					case 4: +					case 5: +						_s17_nextWrenchSequenceId = 0x22E; +						break; +					} +				} else { +					--_s17_wrenchCtr; +					if (_s17_wrenchCtr) { +						switch (getRandom(6)) { +						case 0: +							_s17_nextWrenchSequenceId = 0x237; +							break; +						case 1: +							_s17_nextWrenchSequenceId = 0x238; +							break; +						case 2: +							_s17_nextWrenchSequenceId = 0x239; +							break; +						case 3: +							_s17_nextWrenchSequenceId = 0x23A; +							break; +						case 4: +							_s17_nextWrenchSequenceId = 0x23B; +							break; +						case 5: +							_s17_nextWrenchSequenceId = 0x235; +							break; +						} +					} else { +						_s17_wrenchCtr = 2; +						_s17_nextWrenchSequenceId = 0x235; +					} +				} +			} +			if (!_timers[6]) { +				_timers[6] = getRandom(30) + 200; +				if (_s17_nextCarWindowSequenceId == -1 && !isFlag(6)) +					_s17_nextCarWindowSequenceId = 0x246; +			} +			playSoundA(); +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene17_updateHotspots(); +		} +		 +		gameUpdateTick(); +		 +	} + +} + +void GnapEngine::scene17_updateAnimations() { + +	static const int kPlatPhoneSequenceIds[] = { +		0x251, 0x252, 0x253, 0x254, 0x255, 0x256, 0x257 +	}; + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASGetWrench1: +			_gnapActionStatus = kASGetWrenchGnapReady; +			break; +		case kASGetCoinFromPhone: +			playGnapPullOutDevice(1, 3); +			playGnapUseDevice(0, 0); +			_gameSys->setAnimation(0x250, 100, 0); +			_gameSys->insertSequence(0x250, 100, 591, 100, kSeqSyncWait, 0, 0, 0); +			invAdd(kItemDiceQuarterHole); +			clearFlag(18); +			_gnapActionStatus = kASGetCoinFromPhoneDone; +			break; +		case kASGetCoinFromPhoneDone: +			setGrabCursorSprite(kItemDiceQuarterHole); +			_gnapActionStatus = -1; +			break; +		case kASPutCoinIntoPhone: +			_gameSys->setAnimation(0x24C, _gnapId, 0); +			_gameSys->insertSequence(0x24C, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x24C; +			invRemove(kItemDiceQuarterHole); +			setGrabCursorSprite(-1); +			setFlag(18); +			_gnapActionStatus = kASPutCoinIntoPhoneDone; +			break; +		case kASPutCoinIntoPhoneDone: +			_gameSys->insertSequence(0x24F, 100, 0, 0, kSeqNone, 0, 0, 0); +			_gnapActionStatus = -1; +			break; +		case kASGnapUsePhone: +			_gameSys->setAnimation(0x24D, _gnapId, 0); +			_gameSys->insertSequence(0x24D, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapActionStatus = kASLeaveScene; +			_newSceneNum = 53; +			break; +		case kASGnapHangUpPhone: +			_gameSys->insertSequence(0x258, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x258; +			_gnapActionStatus = -1; +			break; +		case kASLeaveScene: +			_sceneDone = true; +			break; +		} +	} + +	if (_gameSys->getAnimationStatus(1) == 2) { +		_gameSys->setAnimation(0, 0, 1); +		switch (_beaverActionStatus) { +		case kASTryGetWrench: +			_beaverActionStatus = -1; +			++_s17_platTryGetWrenchCtr; +			if (_s17_platTryGetWrenchCtr % 2 != 0) +				_s17_nextWrenchSequenceId = 0x233; +			else +				_s17_nextWrenchSequenceId = 0x234; +			_s17_canTryGetWrench = false; +			break; +		case kASGetWrench1: +			_s17_nextWrenchSequenceId = 0x230; +			break; +		case kASGetWrench2: +			_s17_nextCarWindowSequenceId = 0x249; +			break; +		case kASGetWrenchDone: +			_beaverActionStatus = -1; +			invAdd(kItemWrench); +			setGrabCursorSprite(kItemWrench); +			break; +		case kASPlatUsePhone: +			_gameSys->setAnimation(0x24E, _beaverId, 1); +			_gameSys->insertSequence(0x24E, _beaverId, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0); +			_beaverSequenceDatNum = 0; +			_beaverSequenceId = 0x24E; +			_beaverActionStatus = kASLeaveScene; +			_newSceneNum = 53; +			break; +		case kASPlatPhoningAssistant: +			++_s17_platPhoneCtr; +			if (_s17_platPhoneCtr >= 7) { +				_s17_platPhoneCtr = 0; +				_s17_nextPhoneSequenceId = -1; +				_s17_currPhoneSequenceId = -1; +				_gameSys->insertSequence(0x25B, _beaverId, 0x25A, _beaverId, kSeqSyncWait, 0, 0, 0); +				_beaverSequenceDatNum = 0; +				_beaverSequenceId = 0x25B; +				_beaverActionStatus = -1; +				clearFlag(26); +				_sceneWaiting = false; +				scene17_updateHotspots(); +			} else { +				_s17_nextPhoneSequenceId = kPlatPhoneSequenceIds[_s17_platPhoneCtr]; +				_gameSys->setAnimation(_s17_nextPhoneSequenceId, 254, 1); +				_gameSys->insertSequence(_s17_nextPhoneSequenceId, 254, _s17_currPhoneSequenceId, 254, kSeqSyncWait, 0, 0, 0); +				_gameSys->insertSequence(0x25A, _beaverId, 0x25A, _beaverId, kSeqSyncWait, 0, 0, 0); +				_beaverSequenceDatNum = 0; +				_beaverSequenceId = 0x25A; +				_s17_currPhoneSequenceId = _s17_nextPhoneSequenceId; +			} +			break; +		case kASLeaveScene: +			_sceneDone = true; +			break; +		} +	} + +	if (_gameSys->getAnimationStatus(2) == 2) { +		switch (_s17_nextWrenchSequenceId) { +		case 0x233: +			_gnapActionStatus = -1; +			_gameSys->insertSequence(0x243, _beaverId, +				_beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, +				kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(_s17_nextWrenchSequenceId, 40, _s17_currWrenchSequenceId, 40, kSeqSyncWait, 0, 0, 0); +			_s17_currWrenchSequenceId = _s17_nextWrenchSequenceId; +			_s17_nextWrenchSequenceId = -1; +			_beaverSequenceId = 0x243; +			_beaverSequenceDatNum = 0; +			_gameSys->setAnimation(0x243, _beaverId, 1); +			break; +		case 0x234: +			_gnapActionStatus = -1; +			_gameSys->insertSequence(0x242, _beaverId, +				_beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, +				kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(_s17_nextWrenchSequenceId, 40, _s17_currWrenchSequenceId, 40, kSeqSyncWait, 0, 0, 0); +			_s17_currWrenchSequenceId = _s17_nextWrenchSequenceId; +			_s17_nextWrenchSequenceId = -1; +			_beaverSequenceId = 0x242; +			_beaverSequenceDatNum = 0; +			_gameSys->setAnimation(0x242, _beaverId, 1); +			break; +		case 0x231: +			if (getRandom(2) != 0) +				_s17_nextCarWindowSequenceId = 0x245; +			else +				_s17_nextCarWindowSequenceId = 0x248; +			_gameSys->setAnimation(0, 0, 2); +			break; +		case 0x232: +			_s17_nextCarWindowSequenceId = 0x247; +			_gameSys->setAnimation(0, 0, 2); +			break; +		case 0x22E: +		case 0x235: +			if (_s17_nextWrenchSequenceId == 0x235) +				_hotspots[kHSWrench].flags &= ~SF_DISABLED; +			else +				_hotspots[kHSWrench].flags |= SF_DISABLED; +			_s17_canTryGetWrench = !_s17_canTryGetWrench; +			_gameSys->setAnimation(_s17_nextWrenchSequenceId, 40, 2); +			_gameSys->insertSequence(_s17_nextWrenchSequenceId, 40, _s17_currWrenchSequenceId, 40, kSeqSyncWait, 0, 0, 0); +			_s17_currWrenchSequenceId = _s17_nextWrenchSequenceId; +			_s17_nextWrenchSequenceId = -1; +			break; +		case 0x230: +			if (_gnapActionStatus == kASGetWrenchGnapReady) { +				_gameSys->setAnimation(0, 0, 2); +				if (_s17_canTryGetWrench) { +					_gameSys->insertSequence(0x22E, 40, _s17_currWrenchSequenceId, 40, kSeqSyncWait, 0, 0, 0); +					_s17_currWrenchSequenceId = 0x22E; +					_s17_canTryGetWrench = false; +				} +				_gameSys->setAnimation(0x23F, _beaverId, 1); +				_gameSys->insertSequence(0x10875, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +				_gameSys->insertSequence(0x23F, _beaverId, +					_beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, +					kSeqSyncWait, 0, 0, 0); +				_gnapSequenceDatNum = 1; +				_beaverSequenceDatNum = 0; +				_gnapSequenceId = 0x875; +				_beaverSequenceId = 0x23F; +				gnapWalkTo(3, 8, -1, 0x107B9, 1); +				_beaverActionStatus = kASGetWrench2; +			} +			break; +		default: +			if (_s17_nextWrenchSequenceId != -1) { +				_gameSys->setAnimation(_s17_nextWrenchSequenceId, 40, 2); +				_gameSys->insertSequence(_s17_nextWrenchSequenceId, 40, _s17_currWrenchSequenceId, 40, kSeqSyncWait, 0, 0, 0); +				_s17_currWrenchSequenceId = _s17_nextWrenchSequenceId; +				_s17_nextWrenchSequenceId = -1; +			} +			break; +		} +	} + +	if (_gameSys->getAnimationStatus(3) == 2) { +		switch (_s17_nextCarWindowSequenceId) { +		case 0x246: +			_gameSys->setAnimation(_s17_nextCarWindowSequenceId, 40, 3); +			_gameSys->insertSequence(_s17_nextCarWindowSequenceId, 40, _s17_currCarWindowSequenceId, 40, kSeqSyncWait, 0, 0, 0); +			_s17_currCarWindowSequenceId = _s17_nextCarWindowSequenceId; +			_s17_nextCarWindowSequenceId = -1; +			break; +		case 0x245: +		case 0x247: +		case 0x248: +			_gameSys->setAnimation(_s17_nextWrenchSequenceId, 40, 2); +			_gameSys->insertSequence(_s17_nextWrenchSequenceId, 40, _s17_currWrenchSequenceId, 40, kSeqSyncWait, 0, 0, 0); +			while (_gameSys->getAnimationStatus(2) != 2) +				scene17_update(); +			_gameSys->setAnimation(_s17_nextCarWindowSequenceId, 40, 3); +			_gameSys->insertSequence(_s17_nextCarWindowSequenceId, 40, _s17_currCarWindowSequenceId, 40, kSeqSyncWait, 0, 0, 0); +			_s17_currCarWindowSequenceId = _s17_nextCarWindowSequenceId; +			_s17_nextCarWindowSequenceId = -1; +			_s17_currWrenchSequenceId = _s17_nextWrenchSequenceId; +			_s17_nextWrenchSequenceId = -1; +			break; +		case 0x249: +			_gameSys->setAnimation(0x230, 40, 2); +			_gameSys->setAnimation(0x240, _beaverId, 1); +			_gameSys->insertSequence(0x230, 40, _s17_currWrenchSequenceId, 40, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(_s17_nextCarWindowSequenceId, 40, _s17_currCarWindowSequenceId, 40, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x240, _beaverId, _beaverSequenceId, _beaverId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x23E, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x23E; +			_gnapSequenceDatNum = 0; +			_beaverSequenceId = 0x240; +			_beaverSequenceDatNum = 0; +			_gameSys->setAnimation(0x24A, 40, 3); +			_gameSys->insertSequence(0x24A, 40, _s17_nextCarWindowSequenceId, 40, kSeqSyncWait, 0, 0, 0); +			while (_gameSys->getAnimationStatus(2) != 2) { +				scene17_update(); +				if (_gameSys->getAnimationStatus(3) == 2) { +					_gameSys->setAnimation(0x24A, 40, 3); +					_gameSys->insertSequence(0x24A, 40, 586, 40, kSeqSyncWait, 0, 0, 0); +				} +			} +			_gameSys->insertSequence(0x22D, 40, 560, 40, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(0x24B, 40, 3); +			_gameSys->insertSequence(0x24B, 40, 586, 40, kSeqSyncWait, 0, 0, 0); +			_s17_currCarWindowSequenceId = 0x24B; +			_s17_nextCarWindowSequenceId = -1; +			_s17_currWrenchSequenceId = 0x22D; +			_s17_nextWrenchSequenceId = -1; +			setFlag(6); +			_gnapActionStatus = -1; +			_beaverActionStatus = 2; +			scene17_updateHotspots(); +			_timers[5] = getRandom(30) + 80; +			break; +		} +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene18.cpp b/engines/gnap/scenes/scene18.cpp new file mode 100644 index 0000000000..619d50f5e2 --- /dev/null +++ b/engines/gnap/scenes/scene18.cpp @@ -0,0 +1,1026 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +static const int kScene18SequenceIds[] = { +	0x219,  0x21A,  0x21B,  0x21C,  0x21D +}; + +enum { +	kHSPlatypus				= 0, +	kHSGarbageCan			= 1, +	kHSDevice				= 2, +	kHSExitToyStore			= 3, +	kHSExitPhoneBooth		= 4, +	kHSExitGrubCity			= 5, +	kHSHydrantTopValve		= 6, +	kHSHydrantRightValve	= 7, +	kHSCowboyHat			= 8, +	kHSWalkArea1			= 9, +	kHSWalkArea2			= 10 +}; + +enum { +	kASOpenRightValveNoGarbageCanDone		= 0, +	kASOpenRightValveNoGarbageCan			= 1, +	kASCloseRightValveNoGarbageCan			= 2, +	kASOpenTopValveDone						= 3, +	kASOpenTopValve							= 4, +	kASCloseTopValve						= 5, +	kASGrabGarbageCanFromStreet				= 6, +	kASGrabCowboyHat						= 7, +	kASGrabGarbageCanFromHydrant			= 8, +	kASPutGarbageCanOnRunningHydrant		= 9, +	kASPutGarbageCanOnRunningHydrant2		= 10, +	kASGrabCowboyHatDone					= 11, +	kASStandingOnHydrant					= 12, +	kASOpenRightValveWithGarbageCan			= 13, +	kASOpenRightValveWithGarbageCanDone		= 14, +	kASCloseRightValveWithGarbageCan		= 15, +	kASPutGarbageCanOnHydrant				= 16, +	kASPutGarbageCanOnHydrantDone			= 17, +	kASPlatComesHere						= 18, +	kASCloseRightValveWithGarbageCanDone	= 19, +	kASLeaveScene							= 20 +}; + +int GnapEngine::scene18_init() { +	_gameSys->setAnimation(0, 0, 3); +	return 0x222; +} + +void GnapEngine::scene18_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSGarbageCan, _gridMinX + 75 * _s18_garbageCanPos - 35, _gridMinY + 230, _gridMinX + 75 * _s18_garbageCanPos + 35, _gridMinY + 318, +		SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, _s18_garbageCanPos, 7); +	setHotspot(kHSExitToyStore, 460, 238, 592, 442, SF_EXIT_U_CURSOR, 7, 7); +	setHotspot(kHSExitPhoneBooth, 275, 585, 525, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 10); +	setHotspot(kHSExitGrubCity, 0, 350, 15, 600, SF_EXIT_L_CURSOR, 0, 9); +	setHotspot(kHSHydrantTopValve, 100, 345, 182, 410, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 1, 8); +	setHotspot(kHSHydrantRightValve, 168, 423, 224, 470, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 7); +	setHotspot(kHSCowboyHat, 184, 63, 289, 171, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 4, 7); +	setHotspot(kHSWalkArea1, 0, 0, 800, 448); +	setHotspot(kHSWalkArea2, 0, 0, 214, 515); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	if (isFlag(8)) { +		if (isFlag(9)) { +			_hotspots[kHSHydrantTopValve].flags = SF_DISABLED; +			_hotspots[kHSHydrantRightValve].x1 = 148; +			_hotspots[kHSHydrantRightValve].y1 = 403; +			_hotspots[kHSGarbageCan].flags = SF_DISABLED; +			_hotspotsWalkPos[kHSGarbageCan].x = 3; +			_hotspotsWalkPos[kHSGarbageCan].y = 7; +		} else { +			_hotspots[kHSHydrantTopValve].y1 = 246; +		} +	} else if (isFlag(7)) { +		_hotspots[kHSHydrantRightValve].flags = SF_DISABLED; +		_hotspots[kHSHydrantTopValve].x1 = 105; +		_hotspots[kHSHydrantTopValve].x2 = 192; +	} else if (isFlag(9)) { +		_hotspots[kHSGarbageCan].x1 = 115; +		_hotspots[kHSGarbageCan].y1 = 365; +		_hotspots[kHSGarbageCan].x2 = 168; +		_hotspots[kHSGarbageCan].y2 = 470; +		_hotspots[kHSGarbageCan].flags = SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR; +		_hotspotsWalkPos[kHSGarbageCan].x = 3; +		_hotspotsWalkPos[kHSGarbageCan].y = 7; +	} +	if (isFlag(10)) +		_hotspots[kHSGarbageCan].flags = SF_DISABLED; +	if (isFlag(26)) { +		_hotspots[kHSDevice].flags = SF_DISABLED; +		_hotspots[kHSHydrantTopValve].flags = SF_DISABLED; +		_hotspots[kHSHydrantRightValve].flags = SF_DISABLED; +		_hotspots[kHSPlatypus].flags = SF_DISABLED; +	} +	if (isFlag(14)) { +		_hotspots[kHSHydrantTopValve].flags = SF_DISABLED; +		_hotspots[kHSCowboyHat].flags = SF_DISABLED; +	} +	_hotspotsCount = 11; +} + +void GnapEngine::scene18_gnapCarryGarbageCanTo(int x, int y, int animationIndex, int argC, int a5) { + +	// TODO Cleanup +	 +	static const int kSequenceIds[] = { +		0x203, 0x204 +	}; +	 +	int gnapSeqId, gnapId, gnapDatNum, gnapGridX; +	int v13, v12, v5, v10, v11, v15, v16, a2; + +	if (x >= 0) +		v13 = x; +	else +		v13 = (_leftClickMouseX - _gridMinX + 37) / 75; +	if (v13 >= _gnapX) +		v10 = v13 - 1; +	else +		v10 = v13 + 1; + +	if (a5 < 0) +		a5 = 4; +	v5 = v10; +	if (v10 <= a5) +		v5 = a5; +	v11 = v5; +	v12 = _gridMaxX - 1; +	if (_gridMaxX - 1 >= v11) +		v12 = v11; +	 +	if (v12 == _gnapX) { +		gnapSeqId = _gnapSequenceId; +		gnapId = _gnapId; +		gnapDatNum = _gnapSequenceDatNum; +		gnapGridX = _gnapX; +		if (_gnapX <= v13) +			v15 = 1; +		else +			v15 = -1; +	} else { +		if (_gnapY == _platY) { +			if (v12 >= _gnapX) { +				if (v12 >= _platX && _gnapX <= _platX) +					beaverMakeRoom(); +			} else if (v12 <= _platX && _gnapX >= _platX) { +				beaverMakeRoom(); +			} +		} +		gnapSeqId = _gnapSequenceId; +		gnapId = _gnapId; +		gnapDatNum = _gnapSequenceDatNum; +		gnapGridX = _gnapX; +		if (v12 < _gnapX) +			v15 = -1; +		else +			v15 = 1; +		v16 = v15 == -1; +		a2 = 20 * _gnapY + 1; +		do { +			if (isPointBlocked(gnapGridX + v15, _gnapY)) +				break; +			a2 += v15; +			_gameSys->insertSequence(kSequenceIds[v16], a2, +				gnapSeqId | (gnapDatNum << 16), gnapId, +				kSeqSyncWait, 0, 75 * gnapGridX - _gnapGridX, 48 * _gnapY - _gnapGridY); +			gnapSeqId = kSequenceIds[v16]; +			gnapId = a2; +			gnapDatNum = 0; +			gnapGridX += v15; +		} while (v12 != gnapGridX); +	} +	 +	if (argC >= 0) { +		_gnapSequenceId = ridToEntryIndex(argC); +		_gnapSequenceDatNum = ridToDatIndex(argC); +	} else { +		if (v15 == 1) +			_gnapSequenceId = 0x20A; +		else +			_gnapSequenceId = 0x209; +		_gnapSequenceDatNum = 0; +	} +	 +	if (v15 == 1) +		_gnapIdleFacing = 1; +	else +		_gnapIdleFacing = 3; +	 +	_gnapId = 20 * _gnapY + 1; +	 +	if (animationIndex >= 0) +		_gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, animationIndex); +	 +	_gameSys->insertSequence(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +		gnapSeqId | (gnapDatNum << 16), gnapId, +		9, 0, 75 * gnapGridX - _gnapGridX, 48 * _gnapY - _gnapGridY); + +	_gnapX = gnapGridX; + +} + +void GnapEngine::scene18_putDownGarbageCan(int animationIndex) { +	if (animationIndex >= 0) { +		while (_gameSys->getAnimationStatus(animationIndex) != 2) +			gameUpdateTick(); +	} +	if (_gnapIdleFacing != 0 && _gnapIdleFacing != 1 && _gnapIdleFacing != 7) +		_s18_garbageCanPos = _gnapX - 1; +	else +		_s18_garbageCanPos = _gnapX + 1; +	clearFlag(10); +	scene18_updateHotspots(); +	if (_gnapIdleFacing != 0 && _gnapIdleFacing != 1 && _gnapIdleFacing != 7) { +		_gameSys->insertSequence(0x107BA, _gnapId, +			makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +			kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +		_gnapSequenceId = 0x7BA; +	} else { +		_gameSys->insertSequence(0x107B9, _gnapId, +			makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +			kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +		_gnapSequenceId = 0x7B9; +	} +	_gnapSequenceDatNum = 1; +	_gameSys->insertSequence(0x1FB, 19, 0, 0, kSeqNone, 0, 15 * (5 * _s18_garbageCanPos - 40), 0); +	_gameSys->setAnimation(0x1FA, 19, 4); +	_gameSys->insertSequence(0x1FA, 19, 507, 19, kSeqSyncWait, 0, 15 * (5 * _s18_garbageCanPos - 40), 0); +	while (_gameSys->getAnimationStatus(4) != 2) +		gameUpdateTick(); +} + +void GnapEngine::scene18_platEndPhoning(int a1) { +	if (isFlag(26)) { +		_s18_platPhoneIter = 0; +		_s18_platPhoneCtr = 0; +		_beaverActionStatus = -1; +		if (_s18_currPhoneSequenceId != -1) { +			_gameSys->setAnimation(0x21E, 254, 3); +			_gameSys->insertSequence(0x21E, 254, _s18_currPhoneSequenceId, 254, 32, 0, 0, 0); +			while (_gameSys->getAnimationStatus(3) != 2) +				gameUpdateTick(); +		} +		_gameSys->removeSequence(0x21F, 254, 1); +		_gameSys->setAnimation(0, 0, 3); +		clearFlag(26); +		if (a1) { +			_beaverActionStatus = kASPlatComesHere; +			_timers[6] = 50; +			_sceneWaiting = true; +		} +		_s18_currPhoneSequenceId = -1; +		_s18_nextPhoneSequenceId = -1; +		scene18_updateHotspots(); +	} +} + +void GnapEngine::scene18_closeHydrantValve() { +	_gnapActionStatus = kASLeaveScene; +	updateMouseCursor(); +	if (isFlag(8)) { +		gnapWalkTo(_hotspotsWalkPos[kHSHydrantRightValve].x, _hotspotsWalkPos[kHSHydrantRightValve].y, 0, 0x107BA, 1); +		if (isFlag(9)) { +			_gnapActionStatus = kASCloseRightValveWithGarbageCan; +			scene18_waitForGnapAction(); +		} else { +			_gnapActionStatus = kASCloseRightValveNoGarbageCan; +			scene18_waitForGnapAction(); +		} +	} else if (isFlag(7)) { +		gnapWalkTo(_hotspotsWalkPos[kHSHydrantTopValve].x, _hotspotsWalkPos[kHSHydrantTopValve].y, 0, 0x107BA, 1); +		_gnapActionStatus = kASCloseTopValve; +		scene18_waitForGnapAction(); +	} +} + +void GnapEngine::scene18_waitForGnapAction() { +	while (_gnapActionStatus >= 0) { +		scene18_updateAnimations(); +		gameUpdateTick(); +	} +} + +void GnapEngine::scene18_run() { + +	_s18_cowboyHatSurface = 0; + +	playSound(0x10940, 1); +	startSoundTimerA(4); +	 +	_timers[5] = getRandom(100) + 100; +	 +	queueInsertDeviceIcon(); +	 +	clearFlag(10); +	 +	if (!isFlag(14)) +		_gameSys->insertSequence(0x1F8, 19, 0, 0, kSeqNone, 0, 0, 0); + +	if (isFlag(9)) { +		if (isFlag(8)) { +			_gameSys->insertSequence(0x214, 39, 0, 0, kSeqLoop, 0, 0, 0); +			_gameSys->insertSequence(0x20D, 39, 0, 0, kSeqLoop, 0, 0, 0); +			playSound(0x22B, true); +		} else { +			_gameSys->insertSequence(0x1F9, 19, 0, 0, kSeqNone, 0, 0, 0); +		} +	} else { +		_gameSys->insertSequence(0x1FA, 19, 0, 0, kSeqNone, 0, 15 * (5 * _s18_garbageCanPos - 40), 0); +		if (isFlag(8)) { +			_gameSys->insertSequence(0x212, 39, 0, 0, kSeqLoop, 0, 0, 0); +			_gameSys->insertSequence(0x20D, 39, 0, 0, kSeqLoop, 0, 0, 0); +			playSound(0x22B, true); +		} else if (isFlag(7)) { +			_gameSys->insertSequence(0x20E, 39, 0, 0, kSeqLoop, 0, 0, 0); +			_gameSys->insertSequence(0x217, 39, 0, 0, kSeqLoop, 0, 0, 0); +			playSound(0x22B, true); +		} +	} +	 +	if (isFlag(26)) { +		if (_prevSceneNum == 17) +			initGnapPos(4, 11, 1); +		else +			initGnapPos(4, 7, 1); +		_s18_platPhoneCtr = getRandom(5); +		if (isFlag(27)) { +			_gameSys->insertSequence(0x21E, 254, 0, 0, kSeqNone, 0, 0, 0); +			endSceneInit(); +			_s18_currPhoneSequenceId = -1; +			scene18_platEndPhoning(1); +			clearFlag(27); +		} else { +			_s18_currPhoneSequenceId = kScene18SequenceIds[_s18_platPhoneCtr]; +			_s18_platPhoneIter = 0; +			_gameSys->insertSequence(0x21F, 254, 0, 0, kSeqNone, 0, 0, 0); +			_gameSys->insertSequence(_s18_currPhoneSequenceId, 254, 0, 0, kSeqNone, 0, 0, 0); +			endSceneInit(); +		} +		if (isFlag(27)) { +			scene18_platEndPhoning(1); +			clearFlag(27); +		} else { +			_gameSys->setAnimation(_s18_currPhoneSequenceId, 254, 3); +		} +		gnapWalkTo(4, 8, -1, 0x107B9, 1); +	} else { +		if (isFlag(12)) { +			clearFlag(12); +			setGrabCursorSprite(kItemCowboyHat); +			_prevSceneNum = 19; +		} +		if (_prevSceneNum == 17) { +			initGnapPos(4, 11, 1); +			initBeaverPos(5, 11, 0); +			endSceneInit(); +			gnapWalkTo(4, 8, -1, 0x107B9, 1); +			platypusWalkTo(5, 9, -1, 0x107C2, 1); +		} else if (_prevSceneNum == 19) { +			initGnapPos(7, 7, 1); +			initBeaverPos(8, 7, 0); +			endSceneInit(); +			gnapWalkTo(7, 8, -1, 0x107B9, 1); +			platypusWalkTo(8, 8, -1, 0x107C2, 1); +		} else { +			initGnapPos(-1, 10, 1); +			initBeaverPos(-1, 10, 0); +			endSceneInit(); +			gnapWalkTo(3, 7, -1, 0x107B9, 1); +			platypusWalkTo(3, 8, -1, 0x107C2, 1); +		} +	} + +	while (!_sceneDone) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 20, -1, -1, -1, -1); +		 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +		 +		if (_sceneClickedHotspot >= 0) +			debug("_sceneClickedHotspot: %d", _sceneClickedHotspot); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene18_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (isFlag(10)) { +					scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1); +					scene18_putDownGarbageCan(0); +				} +				if (_grabCursorSpriteIndex == kItemJoint) { +					gnapUseJointOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowItem(_grabCursorSpriteIndex, _platX, _platY); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan1(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSCowboyHat: +			if (_gnapActionStatus == kASStandingOnHydrant) { +				_gnapActionStatus = kASGrabCowboyHat; +				_sceneWaiting = 0; +			} else if (_gnapActionStatus < 0) { +				if (isFlag(10)) { +					scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1); +					scene18_putDownGarbageCan(0); +				} +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSCowboyHat].x, _hotspotsWalkPos[kHSCowboyHat].y, 3, 2); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(3, 2); +						break; +					case GRAB_CURSOR: +						gnapWalkTo(_hotspotsWalkPos[kHSCowboyHat].x, _hotspotsWalkPos[kHSCowboyHat].y, 0, getGnapSequenceId(gskPullOutDeviceNonWorking, 3, 2) | 0x10000, 1); +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSGarbageCan: +			if (_gnapActionStatus < 0) { +				if (isFlag(14)) { +					if (_grabCursorSpriteIndex >= 0) +						playGnapShowCurrItem(_hotspotsWalkPos[kHSGarbageCan].x, _hotspotsWalkPos[kHSGarbageCan].y, 1, 5); +					else +						playGnapImpossible(0, 0); +				} else { +					if (isFlag(26)) +						scene18_platEndPhoning(1); +					if (_grabCursorSpriteIndex >= 0) { +						if (!isFlag(9)) +							playGnapShowCurrItem(_hotspotsWalkPos[kHSGarbageCan].x - (_gnapX < _s18_garbageCanPos ? 1 : -1), +								_hotspotsWalkPos[kHSGarbageCan].y, _hotspotsWalkPos[kHSGarbageCan].x, _hotspotsWalkPos[kHSGarbageCan].y); +						else +							playGnapShowCurrItem(_hotspotsWalkPos[kHSGarbageCan].x, _hotspotsWalkPos[kHSGarbageCan].y, 2, 4); +					} else { +						switch (_verbCursor) { +						case LOOK_CURSOR: +							if (!isFlag(9)) +								playGnapScratchingHead(_hotspotsWalkPos[kHSGarbageCan].x - (_gnapX < _s18_garbageCanPos ? 1 : -1), _hotspotsWalkPos[kHSGarbageCan].y); +							else if (!isFlag(8)) +								playGnapScratchingHead(2, 4); +							break; +						case GRAB_CURSOR: +							if (!isFlag(9)) { +								gnapWalkTo(_hotspotsWalkPos[kHSGarbageCan].x - (_gnapX < _s18_garbageCanPos ? 1 : -1), _hotspotsWalkPos[kHSGarbageCan].y, +									-1, -1, 1); +								gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, _s18_garbageCanPos, _gnapY) | 0x10000, 1); +								_gnapActionStatus = kASGrabGarbageCanFromStreet; +							} else if (!isFlag(8)) { +								if (gnapWalkTo(_hotspotsWalkPos[kHSGarbageCan].x, _hotspotsWalkPos[kHSGarbageCan].y, 0, -1, 1)) +									_gnapActionStatus = kASGrabGarbageCanFromHydrant; +							} +							break; +						case TALK_CURSOR: +						case PLAT_CURSOR: +							playGnapImpossible(0, 0); +							break; +						} +					} +				} +			} +			break; + +		case kHSHydrantTopValve: +			if (_gnapActionStatus < 0) { +				if (isFlag(10)) { +					// While carrying garbage can +					if (_grabCursorSpriteIndex >= 0) { +						scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1); +						scene18_putDownGarbageCan(0); +						playGnapShowItem(_grabCursorSpriteIndex, 0, 0); +					} else { +						switch (_verbCursor) { +						case LOOK_CURSOR: +							scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1); +							scene18_putDownGarbageCan(0); +							playGnapScratchingHead(0, 0); +							break; +						case GRAB_CURSOR: +							if (isFlag(8)) { +								scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, 2); +								_gnapActionStatus = kASPutGarbageCanOnRunningHydrant; +							} else if (!isFlag(7)) { +								scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, 2); +								_gnapActionStatus = kASPutGarbageCanOnHydrant; +							} else { +								scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1); +								scene18_putDownGarbageCan(0); +								playGnapImpossible(0, 0); +							} +							break; +						case TALK_CURSOR: +						case PLAT_CURSOR: +							scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1); +							scene18_putDownGarbageCan(0); +							playGnapImpossible(0, 0); +							break; +						} +					} +				} else { +					if (_grabCursorSpriteIndex == kItemWrench) { +						gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, 2, 8) | 0x10000, 1); +						_gnapActionStatus = kASOpenTopValve; +					} else if (_grabCursorSpriteIndex >= 0) { +						playGnapShowCurrItem(_hotspotsWalkPos[kHSHydrantTopValve].x, _hotspotsWalkPos[kHSHydrantTopValve].y, 1, 5); +					} else { +						switch (_verbCursor) { +						case LOOK_CURSOR: +							playGnapScratchingHead(1, 5); +							break; +						case GRAB_CURSOR: +							if (isFlag(7)) { +								_hotspots[kHSWalkArea2].flags |= SF_WALKABLE; +								gnapWalkTo(_hotspotsWalkPos[kHSHydrantTopValve].x, _hotspotsWalkPos[kHSHydrantTopValve].y, 0, 0x107BA, 1); +								_hotspots[kHSWalkArea2].flags &= ~SF_WALKABLE; +								_gnapActionStatus = kASCloseTopValve; +							} else +								playGnapImpossible(0, 0); +							break; +						case TALK_CURSOR: +						case PLAT_CURSOR: +							playGnapImpossible(0, 0); +							break; +						} +					} +				} +			} +			break; + +		case kHSHydrantRightValve: +			if (_gnapActionStatus < 0) { +				if (isFlag(14)) { +					if (_grabCursorSpriteIndex == -1) { +						playGnapImpossible(0, 0); +					} else { +						playGnapShowCurrItem(_hotspotsWalkPos[kHSHydrantRightValve].x, _hotspotsWalkPos[kHSHydrantRightValve].y, 1, 5); +					} +				} else { +					if (isFlag(10)) { +						scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1); +						scene18_putDownGarbageCan(0); +					} +					if (_grabCursorSpriteIndex == kItemWrench) { +						gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, 2, 8) | 0x10000, 1); +						if (isFlag(9)) +							_gnapActionStatus = kASOpenRightValveWithGarbageCan; +						else +							_gnapActionStatus = kASOpenRightValveNoGarbageCan; +					} else if (_grabCursorSpriteIndex >= 0) { +						playGnapShowCurrItem(_hotspotsWalkPos[kHSHydrantRightValve].x, _hotspotsWalkPos[kHSHydrantRightValve].y, 1, 5); +					} else { +						switch (_verbCursor) { +						case LOOK_CURSOR: +							playGnapScratchingHead(1, 5); +							break; +						case GRAB_CURSOR: +							if (isFlag(8)) { +								gnapWalkTo(_hotspotsWalkPos[kHSHydrantRightValve].x, _hotspotsWalkPos[kHSHydrantRightValve].y, 0, 0x107BA, 1); +								if (isFlag(9)) +									_gnapActionStatus = kASCloseRightValveWithGarbageCan; +								else +									_gnapActionStatus = kASCloseRightValveNoGarbageCan; +							} +							break; +						case TALK_CURSOR: +						case PLAT_CURSOR: +							playGnapImpossible(0, 0); +							break; +						} +					} +				} +			} +			break; + +		case kHSExitToyStore: +			if (_gnapActionStatus < 0) { +				if (isFlag(10)) { +					scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1); +					scene18_putDownGarbageCan(0); +				} +				if (isFlag(20)) { +					playGnapImpossible(0, 0); +				} else { +					_isLeavingScene = 1; +					_newSceneNum = 19; +					gnapWalkTo(_hotspotsWalkPos[kHSExitToyStore].x, _hotspotsWalkPos[kHSExitToyStore].y, 0, 0x107C0, 1); +					_gnapActionStatus = kASLeaveScene; +					if (!isFlag(26)) +						platypusWalkTo(_hotspotsWalkPos[kHSExitToyStore].x + 1, _hotspotsWalkPos[kHSExitToyStore].y, -1, 0x107C2, 1); +				} +			} +			break; + +		case kHSExitPhoneBooth: +			if (_gnapActionStatus < 0) { +				if (isFlag(10)) { +					scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1); +					scene18_putDownGarbageCan(0); +				} +				scene18_closeHydrantValve(); +				_isLeavingScene = 1; +				_newSceneNum = 17; +				gnapWalkTo(_hotspotsWalkPos[kHSExitPhoneBooth].x, _hotspotsWalkPos[kHSExitPhoneBooth].y, 0, 0x107AE, 1); +				_gnapActionStatus = kASLeaveScene; +				if (isFlag(26)) +					setFlag(27); +				else +					platypusWalkTo(_hotspotsWalkPos[kHSExitPhoneBooth].x + 1, _hotspotsWalkPos[kHSExitPhoneBooth].y, -1, 0x107C2, 1); +			} +			break; + +		case kHSExitGrubCity: +			if (_gnapActionStatus < 0) { +				if (isFlag(10)) { +					scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1); +					scene18_putDownGarbageCan(0); +				} +				scene18_closeHydrantValve(); +				_isLeavingScene = 1; +				_newSceneNum = 20; +				_hotspots[kHSWalkArea2].flags |= SF_WALKABLE; +				gnapWalkTo(_hotspotsWalkPos[kHSExitGrubCity].x, _hotspotsWalkPos[kHSExitGrubCity].y, 0, 0x107B2, 1); +				_gnapActionStatus = kASLeaveScene; +				if (isFlag(26)) +					scene18_platEndPhoning(0); +				else +					platypusWalkTo(_hotspotsWalkPos[kHSExitGrubCity].x, _hotspotsWalkPos[kHSExitGrubCity].y - 1, -1, 0x107CF, 1); +				_hotspots[kHSWalkArea2].flags &= ~SF_WALKABLE; +			} +			break; + +		case kHSWalkArea1: +		case kHSWalkArea2: +			if (_gnapActionStatus < 0) { +				if (isFlag(10)) { +					scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1); +					scene18_putDownGarbageCan(0); +				} else { +					gnapWalkTo(-1, -1, -1, -1, 1); +				} +				_mouseClickState.left = false; +			} +			break; + +		default: +			if (_gnapActionStatus != kASStandingOnHydrant && _mouseClickState.left) { +				if (isFlag(10)) { +					scene18_gnapCarryGarbageCanTo(-1, -1, 0, -1, -1); +					scene18_putDownGarbageCan(0); +				} else { +					gnapWalkTo(-1, -1, -1, -1, 1); +				} +				_mouseClickState.left = false; +			} +			break; + +		} +	 +		scene18_updateAnimations(); +	 +		if (!isSoundPlaying(0x10940)) +			playSound(0x10940, true); +	 +		if ((isFlag(8) || isFlag(7)) && !isSoundPlaying(0x22B) && +			_gnapActionStatus != kASOpenRightValveNoGarbageCanDone && _gnapActionStatus != kASOpenRightValveNoGarbageCan && +			_gnapActionStatus != kASOpenTopValve && _gnapActionStatus != kASOpenTopValveDone && +			_gnapActionStatus != kASOpenRightValveWithGarbageCan && _gnapActionStatus != kASOpenRightValveWithGarbageCanDone) +			playSound(0x22B, true); +	 +		if (!_isLeavingScene) { +			if (!isFlag(26)) { +				if (_beaverActionStatus == kASPlatComesHere) { +					if (!_timers[6]) { +						_beaverActionStatus = -1; +						_sceneWaiting = false; +						initBeaverPos(-1, 10, 0); +						platypusWalkTo(3, 9, -1, 0x107C2, 1); +						clearFlag(26); +					} +				} else { +					_hotspots[kHSWalkArea1].y2 += 48; +					_hotspots[kHSWalkArea2].x1 += 75; +					updateBeaverIdleSequence(); +					_hotspots[kHSWalkArea2].x1 -= 75; +					_hotspots[kHSWalkArea1].y2 -= 48; +				} +				if (!_timers[5]) { +					_timers[5] = getRandom(100) + 100; +					if (_gnapActionStatus < 0) { +						if (getRandom(2) == 1) +							_gameSys->insertSequence(0x220, 255, 0, 0, kSeqNone, 0, 0, 0); +						else +							_gameSys->insertSequence(0x221, 255, 0, 0, kSeqNone, 0, 0, 0); +					} +				} +				playSoundA(); +			} +			if (!isFlag(10)) +				updateGnapIdleSequence(); +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene18_updateHotspots(); +		} +		 +		gameUpdateTick(); +	 +	} + +	if (isFlag(12)) +		deleteSurface(&_s18_cowboyHatSurface); + +} + +void GnapEngine::scene18_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASGrabGarbageCanFromStreet: +			if (_gnapIdleFacing != 7 && _gnapIdleFacing != 1) { +				_gameSys->insertSequence(0x1FC, _gnapId, +					makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +					kSeqSyncWait, 0, 75 * _gnapX - 675, 0); +				_gnapSequenceDatNum = 0; +				_gnapSequenceId = 0x1FC; +			} else { +				_gameSys->insertSequence(0x1FD, _gnapId, +					makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +					kSeqSyncWait, 0, 75 * _gnapX - 525, 0); +				_gnapSequenceDatNum = 0; +				_gnapSequenceId = 0x1FD; +			} +			_gameSys->removeSequence(0x1FA, 19, 1); +			setFlag(10); +			scene18_updateHotspots(); +			_gnapActionStatus = -1; +			break; +		case kASGrabGarbageCanFromHydrant: +			_gameSys->insertSequence(0x1FE, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->removeSequence(0x1F9, 19, 1); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x1FE; +			clearFlag(9); +			setFlag(10); +			scene18_updateHotspots(); +			_gnapActionStatus = -1; +			break; +		case kASCloseRightValveNoGarbageCan: +			_gameSys->insertSequence(0x205, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->removeSequence(0x20D, 39, 1); +			_gameSys->removeSequence(0x212, 39, 1); +			_gameSys->removeSequence(0x211, 39, 1); +			stopSound(0x22B); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x205; +			clearFlag(8); +			invAdd(kItemWrench); +			setGrabCursorSprite(kItemWrench); +			scene18_updateHotspots(); +			_gnapActionStatus = -1; +			break; +		case kASOpenTopValve: +			setFlag(7); +			scene18_updateHotspots(); +			playGnapPullOutDevice(2, 7); +			playGnapUseDevice(0, 0); +			_gameSys->insertSequence(0x20C, 19, 0, 0, kSeqNone, 0, 0, 0); +			_hotspots[kHSWalkArea2].flags |= SF_WALKABLE; +			gnapWalkTo(_hotspotsWalkPos[kHSHydrantTopValve].x, _hotspotsWalkPos[kHSHydrantTopValve].y, 0, 0x107BB, 1); +			_hotspots[kHSWalkArea2].flags &= ~SF_WALKABLE; +			_gnapActionStatus = kASOpenTopValveDone; +			break; +		case kASOpenTopValveDone: +			setGrabCursorSprite(-1); +			_gameSys->insertSequence(0x208, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x216, 39, 0, 0, kSeqNone, 21, 0, 0); +			_gameSys->removeSequence(0x20C, 19, 1); +			_gameSys->setAnimation(0x217, 39, 5); +			_gameSys->insertSequence(0x217, 39, 0x216, 39, 10, 0, 0, 0); +			while (_gameSys->getAnimationStatus(5) != 2) +				gameUpdateTick(); +			playSound(0x22B, true); +			_gameSys->insertSequence(0x20E, 39, 0, 0, kSeqNone, 0, 0, 0); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x208; +			invRemove(kItemWrench); +			setGrabCursorSprite(-1); +			_gnapActionStatus = -1; +			break; +		case kASCloseTopValve: +			_gameSys->insertSequence(0x206, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->removeSequence(0x20E, 39, 1); +			_gameSys->removeSequence(0x216, 39, 1); +			_gameSys->removeSequence(0x217, 39, 1); +			stopSound(0x22B); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x206; +			clearFlag(7); +			invAdd(kItemWrench); +			setGrabCursorSprite(kItemWrench); +			scene18_updateHotspots(); +			_gnapActionStatus = -1; +			break; +		case kASGrabCowboyHat: +			_gameSys->setAnimation(0x200, _gnapId, 0); +			_gameSys->insertSequence(0x200, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x200; +			_gnapActionStatus = kASGrabCowboyHatDone; +			break; +		case kASGrabCowboyHatDone: +			hideCursor(); +			setGrabCursorSprite(-1); +			_s18_cowboyHatSurface = addFullScreenSprite(0x1D2, 255); +			_gameSys->setAnimation(0x218, 256, 0); +			_gameSys->insertSequence(0x218, 256, 0, 0, kSeqNone, 0, 0, 0); +			while (_gameSys->getAnimationStatus(0) != 2) +				gameUpdateTick(); +			_newSceneNum = 18; +			invAdd(kItemCowboyHat); +			invAdd(kItemWrench); +			setFlag(12); +			setFlag(14); +			clearFlag(8); +			setFlag(9); +			setFlag(14); +			scene18_updateHotspots(); +			_gnapActionStatus = kASLeaveScene; +			break; +		case kASLeaveScene: +			_sceneDone = true; +			_gnapActionStatus = -1; +			break; +		case kASPutGarbageCanOnRunningHydrant: +			setFlag(9); +			clearFlag(10); +			_gameSys->requestRemoveSequence(0x211, 39); +			_gameSys->requestRemoveSequence(0x212, 39); +			_gameSys->insertSequence(0x210, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			stopSound(0x22B); +			_gameSys->setAnimation(0x210, _gnapId, 0); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x210; +			_gnapActionStatus = kASPutGarbageCanOnRunningHydrant2; +			break; +		case kASPutGarbageCanOnRunningHydrant2: +			playSound(0x22B, true); +			_gameSys->setAnimation(0x1FF, _gnapId, 0); +			_gameSys->insertSequence(0x1FF, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x1FF; +			_sceneWaiting = true; +			_gnapActionStatus = kASStandingOnHydrant; +			break; +		case kASStandingOnHydrant: +			_gameSys->setAnimation(0x1FF, _gnapId, 0); +			_gameSys->insertSequence(0x1FF, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			break; +		case kASOpenRightValveNoGarbageCan: +		case kASOpenRightValveWithGarbageCan: +			setFlag(8); +			scene18_updateHotspots(); +			playGnapPullOutDevice(2, 7); +			playGnapUseDevice(0, 0); +			_gameSys->insertSequence(0x20B, 19, 0, 0, kSeqNone, 0, 0, 0); +			_hotspots[kHSWalkArea2].flags |= SF_WALKABLE; +			gnapWalkTo(_hotspotsWalkPos[kHSHydrantRightValve].x, _hotspotsWalkPos[kHSHydrantRightValve].y, 0, 0x107BA, 1); +			_hotspots[kHSWalkArea2].flags &= ~SF_WALKABLE; +			if (_gnapActionStatus == kASOpenRightValveNoGarbageCan) +				_gnapActionStatus = kASOpenRightValveNoGarbageCanDone; +			else +				_gnapActionStatus = kASOpenRightValveWithGarbageCanDone; +			break; +		case kASOpenRightValveWithGarbageCanDone: +			setGrabCursorSprite(-1); +			_gameSys->insertSequence(0x207, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x213, 39, 0, 0, kSeqNone, 21, 0, 0); +			_gameSys->requestRemoveSequence(0x1F9, 19); +			_gameSys->removeSequence(0x20B, 19, 1); +			_gameSys->setAnimation(0x213, 39, 5); +			_gameSys->insertSequence(0x214, 39, 0x213, 39, 10, 0, 0, 0); +			while (_gameSys->getAnimationStatus(5) != 2) +				gameUpdateTick(); +			playSound(555, true); +			_gameSys->insertSequence(0x20D, 39, 0, 0, kSeqNone, 0, 0, 0); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x207; +			invRemove(kItemWrench); +			_gnapActionStatus = -1; +			break; +		case kASOpenRightValveNoGarbageCanDone: +			setGrabCursorSprite(-1); +			_gameSys->insertSequence(0x207, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x211, 39, 0, 0, kSeqNone, 21, 0, 0); +			_gameSys->removeSequence(0x20B, 19, 1); +			_gameSys->setAnimation(0x211, 39, 5); +			_gameSys->insertSequence(0x212, 39, 0x211, 39, 10, 0, 0, 0); +			while (_gameSys->getAnimationStatus(5) != 2) +				gameUpdateTick(); +			playSound(0x22B, true); +			_gameSys->insertSequence(0x20D, 39, 0, 0, kSeqNone, 0, 0, 0); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x207; +			invRemove(kItemWrench); +			_gnapActionStatus = -1; +			break; +		case kASCloseRightValveWithGarbageCan: +			_gameSys->insertSequence(0x205, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->removeSequence(0x20D, 39, 1); +			_gameSys->insertSequence(0x215, 39, 0x214, 39, kSeqSyncWait, 0, 0, 0); +			stopSound(0x22B); +			_gameSys->setAnimation(0x1F9, 19, 0); +			_gameSys->insertSequence(0x1F9, 19, 0x215, 39, kSeqSyncWait, 0, 0, 0); +			clearFlag(8); +			invAdd(kItemWrench); +			setGrabCursorSprite(kItemWrench); +			_gameSys->insertSequence(0x107B5, _gnapId, 517, _gnapId, kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +			scene18_updateHotspots(); +			_gnapSequenceDatNum = 1; +			_gnapSequenceId = 0x7B5; +			_gnapActionStatus = kASCloseRightValveWithGarbageCanDone; +			break; +		case kASCloseRightValveWithGarbageCanDone: +			_gnapActionStatus = -1; +			break; +		case kASPutGarbageCanOnHydrant: +			setFlag(9); +			clearFlag(10); +			_gameSys->insertSequence(0x20F, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(0x20F, _gnapId, 0); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x20F; +			_gnapActionStatus = kASPutGarbageCanOnHydrantDone; +			break; +		case kASPutGarbageCanOnHydrantDone: +			_gameSys->insertSequence(0x1F9, 19, 0x20F, _gnapId, kSeqNone, 0, 0, 0); +			scene18_updateHotspots(); +			_gnapActionStatus = -1; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2) { +		_gameSys->setAnimation(0, 0, 3); +		++_s18_platPhoneIter; +		if (_s18_platPhoneIter <= 4) { +			++_s18_platPhoneCtr; +			_s18_nextPhoneSequenceId = kScene18SequenceIds[_s18_platPhoneCtr % 5]; +			_gameSys->setAnimation(_s18_nextPhoneSequenceId, 254, 3); +			_gameSys->insertSequence(_s18_nextPhoneSequenceId, 254, _s18_currPhoneSequenceId, 254, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x21F, 254, 0x21F, 254, kSeqSyncWait, 0, 0, 0); +			_s18_currPhoneSequenceId = _s18_nextPhoneSequenceId; +		} else { +			scene18_platEndPhoning(1); +		} +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene19.cpp b/engines/gnap/scenes/scene19.cpp new file mode 100644 index 0000000000..ebfdd728a1 --- /dev/null +++ b/engines/gnap/scenes/scene19.cpp @@ -0,0 +1,470 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +static const int kS19ShopAssistantSequenceIds[] = { +	0x6F, 0x70, 0x71, 0x72, 0x73 +}; + +enum { +	kHSPlatypus				= 0, +	kHSExitOutsideToyStore	= 1, +	kHSDevice				= 2, +	kHSPicture				= 3, +	kHSShopAssistant		= 4, +	kHSToy1					= 5, +	kHSToy2					= 6, +	kHSToy3					= 7, +	kHSPhone				= 8, +	kHSToy4					= 9, +	kHSToy5					= 10, +	kHSToy6					= 11, +	kHSToy7					= 12, +	kHSWalkArea1			= 13, +	kHSWalkArea2			= 14, +	kHSWalkArea3			= 15 +}; + +enum { +	kASUsePhone					= 0, +	kASGrabToy					= 1, +	kASGrabPicture				= 2, +	kASGrabPictureDone			= 3, +	kASTalkShopAssistant		= 4, +	kASLeaveScene				= 5 +}; + +int GnapEngine::scene19_init() { +	playSound(0x79, 0); +	return isFlag(26) ? 0x77 : 0x76; +} + +void GnapEngine::scene19_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitOutsideToyStore, 36, 154, 142, 338, SF_EXIT_NW_CURSOR, 4, 6); +	setHotspot(kHSPicture, 471, 237, 525, 283, SF_DISABLED, 7, 2); +	setHotspot(kHSShopAssistant, 411, 151, 575, 279, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 5, 7); +	setHotspot(kHSPhone, 647, 166, 693, 234, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 9, 0); +	setHotspot(kHSToy1, 181, 11, 319, 149, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 0); +	setHotspot(kHSToy2, 284, 85, 611, 216, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 0); +	setHotspot(kHSToy3, 666, 38, 755, 154, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 9, 0); +	setHotspot(kHSToy4, 154, 206, 285, 327, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 3); +	setHotspot(kHSToy5, 494, 301, 570, 448, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 5); +	setHotspot(kHSToy6, 0, 320, 188, 600, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 1, 6); +	setHotspot(kHSToy7, 597, 434, 800, 600, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 9, 8); +	setHotspot(kHSWalkArea1, 0, 0, 170, 600); +	setHotspot(kHSWalkArea2, 622, 0, 800, 600); +	setHotspot(kHSWalkArea3, 0, 0, 800, 437); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	if (isFlag(26)) { +		_hotspots[kHSToy1].flags = SF_DISABLED; +		_hotspots[kHSToy2].flags = SF_DISABLED; +		_hotspots[kHSToy3].flags = SF_DISABLED; +		_hotspots[kHSToy4].flags = SF_DISABLED; +		_hotspots[kHSToy5].flags = SF_DISABLED; +		_hotspots[kHSToy6].flags = SF_DISABLED; +		_hotspots[kHSToy7].flags = SF_DISABLED; +		_hotspots[kHSShopAssistant].flags = SF_DISABLED; +		_hotspots[kHSPhone].flags = SF_DISABLED; +		_hotspots[kHSPlatypus].flags = SF_DISABLED; +		_hotspots[kHSPicture].flags = SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR; +	} +	_hotspotsCount = 16; +} + +void GnapEngine::scene19_run() { + +	queueInsertDeviceIcon(); + +	_s19_toyGrabCtr = 0; +	_s19_pictureSurface = 0; + +	_gameSys->insertSequence(0x74, 254, 0, 0, kSeqNone, 0, 0, 0); +	_gameSys->insertSequence(0x75, 254, 0, 0, kSeqNone, 0, 0, 0); + +	if (!isFlag(20)) +		_gameSys->insertSequence(0x69, 19, 0, 0, kSeqNone, 0, 0, 0); + +	if (isFlag(26)) { +		initGnapPos(3, 6, 1); +		_s19_currShopAssistantSequenceId = kS19ShopAssistantSequenceIds[getRandom(5)]; +		_s19_nextShopAssistantSequenceId = _s19_currShopAssistantSequenceId; +		_gameSys->setAnimation(_s19_currShopAssistantSequenceId, 20, 4); +		_gameSys->insertSequence(0x6E, 254, 0, 0, kSeqNone, 0, 0, 0); +		_gameSys->insertSequence(_s19_currShopAssistantSequenceId, 20, 0, 0, kSeqNone, 0, 0, 0); +		_s19_shopAssistantCtr = 0; +		endSceneInit(); +		gnapWalkTo(4, 9, -1, 0x107B9, 1); +		scene19_updateHotspots(); +	} else { +		_s19_currShopAssistantSequenceId = 0x6D; +		_s19_nextShopAssistantSequenceId = -1; +		_gameSys->setAnimation(0x6D, 20, 4); +		_gameSys->insertSequence(_s19_currShopAssistantSequenceId, 20, 0, 0, kSeqNone, 0, 0, 0); +		_timers[6] = getRandom(40) + 50; +		initGnapPos(3, 6, 1); +		initBeaverPos(4, 6, 0); +		endSceneInit(); +		gnapWalkTo(4, 9, -1, 0x107B9, 1); +		platypusWalkTo(5, 9, -1, 0x107C2, 1); +	} +	 +	while (!_sceneDone) { + +		updateMouseCursor(); +		updateCursorByHotspot(); + +		testWalk(0, 5, -1, -1, -1, -1); + +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); + +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene19_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemJoint) { +					gnapUseJointOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(_platX, _platY); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan1(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSExitOutsideToyStore: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				_newSceneNum = 18; +				_hotspots[kHSWalkArea1].flags |= SF_WALKABLE; +				gnapWalkTo(_hotspotsWalkPos[1].x, _hotspotsWalkPos[1].y, 0, 0x107B2, 1); +				_gnapActionStatus = kASLeaveScene; +				if (isFlag(26)) +					setFlag(27); +				else +					platypusWalkTo(_hotspotsWalkPos[1].x + 1, _hotspotsWalkPos[1].y, -1, 0x107C5, 1); +				_hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE; +			} +			break; + +		case kHSPicture: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 6, 2); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(6, 2); +						break; +					case GRAB_CURSOR: +						if (!isFlag(20)) { +							gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, _hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y) | 0x10000, 1); +							_gnapActionStatus = kASGrabPicture; +						} +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSShopAssistant: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 6, 2); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(6, 2); +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASTalkShopAssistant; +						break; +					case GRAB_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSToy1: +		case kHSToy2: +		case kHSToy3: +		case kHSToy4: +		case kHSToy5: +		case kHSToy6: +		case kHSToy7: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan2(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y); +						break; +					case GRAB_CURSOR: +						gnapWalkTo(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 0, -1, 1); +						playGnapIdle(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y); +						_gnapActionStatus = kASGrabToy; +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSPhone: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 9, 1); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(9, 1); +						break; +					case GRAB_CURSOR: +						gnapWalkTo(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, 0, -1, 1); +						playGnapIdle(8, 2); +						_gnapActionStatus = kASUsePhone; +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSWalkArea1: +		case kHSWalkArea2: +		case kHSWalkArea3: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; + +		default: +			if (_mouseClickState.left) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = 0; +			} +		} + +		scene19_updateAnimations(); +	 +		if (!_isLeavingScene) { +			updateGnapIdleSequence(); +			if (!isFlag(26)) { +				updateBeaverIdleSequence(); +				if (!_timers[6] && _s19_nextShopAssistantSequenceId == -1) { +					_timers[6] = getRandom(40) + 50; +					if (getRandom(4) != 0) { +						_s19_nextShopAssistantSequenceId = 0x64; +					} else if (isFlag(20)) { +						_s19_nextShopAssistantSequenceId = 0x64; +					} else { +						_s19_nextShopAssistantSequenceId = 0x6C; +					} +				} +			} +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene19_updateHotspots(); +		} +		 +		gameUpdateTick(); + +	} + +	if (_s19_pictureSurface) +		deleteSurface(&_s19_pictureSurface); + +} + +void GnapEngine::scene19_updateAnimations() { +	 +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASUsePhone: +			_s19_nextShopAssistantSequenceId = 0x67; +			break; +		case kASGrabToy: +			++_s19_toyGrabCtr; +			switch (_s19_toyGrabCtr) { +			case 1: +				_s19_nextShopAssistantSequenceId = 0x62; +				break; +			case 2: +				_s19_nextShopAssistantSequenceId = 0x6B; +				break; +			case 3: +				_s19_nextShopAssistantSequenceId = 0x66; +				break; +			default: +				_s19_nextShopAssistantSequenceId = 0x65; +				break; +			} +			break; +		case kASGrabPicture: +			playGnapPullOutDevice(6, 2); +			playGnapUseDevice(0, 0); +			_gameSys->setAnimation(0x68, 19, 0); +			_gameSys->insertSequence(0x68, 19, 105, 19, kSeqSyncWait, 0, 0, 0); +			invAdd(kItemPicture); +			setFlag(20); +			scene19_updateHotspots(); +			_gnapActionStatus = kASGrabPictureDone; +			break; +		case kASGrabPictureDone: +			setGrabCursorSprite(-1); +			hideCursor(); +			_s19_pictureSurface = addFullScreenSprite(0xF, 255); +			_gameSys->setAnimation(0x61, 256, 0); +			_gameSys->insertSequence(0x61, 256, 0, 0, kSeqNone, 0, 0, 0); +			while (_gameSys->getAnimationStatus(0) != 2) { +				// checkGameAppStatus(); +				gameUpdateTick(); +			} +			setFlag(27); +			showCursor(); +			_newSceneNum = 17; +			_isLeavingScene = true; +			_sceneDone = true; +			_s19_nextShopAssistantSequenceId = -1; +			break; +		case kASTalkShopAssistant: +			_s19_nextShopAssistantSequenceId = 0x6D; +			_gnapActionStatus = -1; +			break; +		case kASLeaveScene: +			_sceneDone = true; +			break; +		} +	} + +	if (_gameSys->getAnimationStatus(4) == 2) { +		switch (_s19_nextShopAssistantSequenceId) { +		case 0x6F: +		case 0x70: +		case 0x71: +		case 0x72: +		case 0x73: +			_s19_shopAssistantCtr = (_s19_shopAssistantCtr + 1) % 5; +			_s19_nextShopAssistantSequenceId = kS19ShopAssistantSequenceIds[_s19_shopAssistantCtr]; +			_gameSys->setAnimation(_s19_nextShopAssistantSequenceId, 20, 4); +			_gameSys->insertSequence(_s19_nextShopAssistantSequenceId, 20, _s19_currShopAssistantSequenceId, 20, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x6E, 254, 0x6E, 254, kSeqSyncWait, 0, 0, 0); +			_s19_currShopAssistantSequenceId = _s19_nextShopAssistantSequenceId; +			break; +		case 0x62: +		case 0x66: +		case 0x6B: +			_gameSys->setAnimation(_s19_nextShopAssistantSequenceId, 20, 4); +			_gameSys->insertSequence(_s19_nextShopAssistantSequenceId, 20, _s19_currShopAssistantSequenceId, 20, kSeqSyncWait, 0, 0, 0); +			_s19_currShopAssistantSequenceId = _s19_nextShopAssistantSequenceId; +			_s19_nextShopAssistantSequenceId = -1; +			_timers[5] = 10; +			while (_timers[5]) { +				gameUpdateTick(); +			} +			playGnapIdle(6, 2); +			_gnapActionStatus = -1; +			break; +		case 0x67: +			_gameSys->setAnimation(_s19_nextShopAssistantSequenceId, 20, 4); +			_gameSys->insertSequence(_s19_nextShopAssistantSequenceId, 20, _s19_currShopAssistantSequenceId, 20, kSeqSyncWait, 0, 0, 0); +			_s19_currShopAssistantSequenceId = _s19_nextShopAssistantSequenceId; +			_s19_nextShopAssistantSequenceId = -1; +			_gnapActionStatus = -1; +			break; +		case 0x65: +			playGnapIdle(6, 2); +			_gameSys->setAnimation(_s19_nextShopAssistantSequenceId, 20, 0); +			_gameSys->insertSequence(_s19_nextShopAssistantSequenceId, 20, _s19_currShopAssistantSequenceId, 20, kSeqSyncWait, 0, 0, 0); +			_s19_currShopAssistantSequenceId = _s19_nextShopAssistantSequenceId; +			_s19_nextShopAssistantSequenceId = -1; +			_newSceneNum = 18; +			_gnapActionStatus = kASLeaveScene; +			break; +		case 0x6D: +			_gameSys->setAnimation(_s19_nextShopAssistantSequenceId, 20, 4); +			_gameSys->insertSequence(_s19_nextShopAssistantSequenceId, 20, _s19_currShopAssistantSequenceId, 20, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x69, 19, 0x69, 19, kSeqSyncWait, getSequenceTotalDuration(_s19_nextShopAssistantSequenceId), 0, 0); +			_s19_currShopAssistantSequenceId = _s19_nextShopAssistantSequenceId; +			_s19_nextShopAssistantSequenceId = -1; +			break; +		case 0x64: +		case 0x6C: +			_gameSys->setAnimation(_s19_nextShopAssistantSequenceId, 20, 4); +			_gameSys->insertSequence(_s19_nextShopAssistantSequenceId, 20, _s19_currShopAssistantSequenceId, 20, kSeqSyncWait, 0, 0, 0); +			_s19_currShopAssistantSequenceId = _s19_nextShopAssistantSequenceId; +			_s19_nextShopAssistantSequenceId = -1; +			break; +		} +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene20.cpp b/engines/gnap/scenes/scene20.cpp new file mode 100644 index 0000000000..136f234bce --- /dev/null +++ b/engines/gnap/scenes/scene20.cpp @@ -0,0 +1,736 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus					= 0, +	kHSGroceryStoreHat			= 1, +	kHSExitParkingLot			= 2, +	kHSStonerGuy				= 3, +	kHSGroceryStoreGuy			= 4, +	kHSDevice					= 5, +	kHSExitInsideGrubCity		= 6, +	kHSExitOutsideCircusWorld	= 7, +	kHSExitOutsideToyStore		= 8, +	kHSExitPhone				= 9, +	kHSWalkArea1				= 10, +	kHSWalkArea2				= 11 +}; + +enum { +	kASLeaveScene					= 0, +	kASTalkStonerGuyNoJoint			= 2, +	kASTalkStonerGuyHasJoint		= 3, +	kASGrabJoint					= 4, +	kASActionDone					= 5, +	kASTalkGroceryStoreGuy			= 6, +	kASGrabGroceryStoreGuy			= 9, +	kASGrabGroceryStoreHat			= 10, +	kASSwitchGroceryStoreHat		= 11, +	kASSwitchGroceryStoreHatDone	= 12, +	kASGrabJointDone				= 13 +}; + +int GnapEngine::scene20_init() { +	return 0x186; +} + +void GnapEngine::scene20_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSGroceryStoreHat, 114, 441, 174, 486, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 0, 7); +	setHotspot(kHSExitParkingLot, 0, 300, 15, 600, SF_EXIT_L_CURSOR | SF_WALKABLE, 0, 7); +	setHotspot(kHSStonerGuy, 276, 290, 386, 450, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 8); +	setHotspot(kHSGroceryStoreGuy, 123, 282, 258, 462, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 7); +	setHotspot(kHSExitInsideGrubCity, 519, 250, 581, 413, SF_EXIT_L_CURSOR, 8, 7); +	setHotspot(kHSExitOutsideCircusWorld, 660, 222, 798, 442, SF_EXIT_NE_CURSOR, 9, 6); +	setHotspot(kHSExitOutsideToyStore, 785, 350, 800, 600, SF_EXIT_R_CURSOR, 11, 8); +	setHotspot(kHSExitPhone, 250, 585, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 10); +	setHotspot(kHSWalkArea1, 0, 0, 800, 468); +	setHotspot(kHSWalkArea2, 605, 0, 800, 600); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 12; +} + +void GnapEngine::scene20_updateAnimationsCb() { + +	if (_gameSys->getAnimationStatus(2) == 2) { +		switch (_s20_nextStonerGuySequenceId) { +		case 0x16B: +			if (!_timers[4]) { +				_s20_stonerGuyShowingJoint = false; +				_gameSys->insertSequence(0x16B, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0); +				_s20_currStonerGuySequenceId = 0x16B; +				_s20_nextStonerGuySequenceId = -1; +			} +			break; +		case 0x16A: +			// Grab joint +			playGnapPullOutDevice(4, 4); +			playGnapUseDevice(0, 0); +			_gameSys->setAnimation(0x16A, 21, 0); +			_gameSys->insertSequence(0x16A, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0); +			_s20_currStonerGuySequenceId = 0x16A; +			_s20_nextStonerGuySequenceId = -1; +			invAdd(kItemJoint); +			setFlag(17); +			_s20_stonerGuyShowingJoint = false; +			_gnapActionStatus = kASGrabJointDone; +			break; +		case 0x16E: +			_gameSys->setAnimation(0x16E, 21, 2); +			_gameSys->insertSequence(0x16E, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0); +			_s20_currStonerGuySequenceId = 0x16E; +			_s20_nextStonerGuySequenceId = -1; +			_s20_nextGroceryStoreGuySequenceId = 0x175; +			break; +		case 0x16D: +			_gameSys->setAnimation(_s20_nextStonerGuySequenceId, 21, 2); +			_gameSys->setAnimation(_s20_nextStonerGuySequenceId, 21, 0); +			_gameSys->insertSequence(_s20_nextStonerGuySequenceId, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0); +			_s20_currStonerGuySequenceId = _s20_nextStonerGuySequenceId; +			_s20_nextStonerGuySequenceId = -1; +			_gnapActionStatus = kASActionDone; +			break; +		case 0x16F: +			_gameSys->setAnimation(_s20_nextStonerGuySequenceId, 21, 2); +			_gameSys->setAnimation(0x17A, 20, 3); +			_gameSys->insertSequence(_s20_nextStonerGuySequenceId, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x17A, 20, _s20_currGroceryStoreGuySequenceId, 20, kSeqSyncWait, 0, 0, 0); +			_s20_currGroceryStoreGuySequenceId = 0x17A; +			_s20_nextGroceryStoreGuySequenceId = -1; +			_s20_currStonerGuySequenceId = _s20_nextStonerGuySequenceId; +			_s20_nextStonerGuySequenceId = -1; +			break; +		case 0x171: +			_s20_stonerGuyCtr = (_s20_stonerGuyCtr + 1) % 3; +			switch (_s20_stonerGuyCtr) { +			case 1: +				_s20_nextStonerGuySequenceId = 0x171; +				break; +			case 2: +				_s20_nextStonerGuySequenceId = 0x172; +				break; +			case 3: +				_s20_nextStonerGuySequenceId = 0x173; +				break; +			default: +				_s20_nextStonerGuySequenceId = 0x171; +				break; +			} +			_gameSys->insertSequence(_s20_nextStonerGuySequenceId, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x17C, 20, _s20_currGroceryStoreGuySequenceId, 20, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(0x17C, 20, 3); +			_gameSys->setAnimation(_s20_nextStonerGuySequenceId, 21, 2); +			_s20_currGroceryStoreGuySequenceId = 0x17C; +			_s20_nextGroceryStoreGuySequenceId = -1; +			_s20_currStonerGuySequenceId = _s20_nextStonerGuySequenceId; +			_s20_nextStonerGuySequenceId = -1; +			break; +		default: +			_s20_nextStonerGuySequenceId = 0x16C; +			_gameSys->setAnimation(0x16C, 21, 2); +			_gameSys->insertSequence(_s20_nextStonerGuySequenceId, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0); +			_s20_currStonerGuySequenceId = _s20_nextStonerGuySequenceId; +			_s20_nextStonerGuySequenceId = -1; +			break; +		} +	} + +} + +void GnapEngine::scene20_stopSounds() { +	stopSound(0x18E); +	stopSound(0x18F); +	stopSound(0x190); +	stopSound(0x191); +	stopSound(0x194); +	stopSound(0x195); +	stopSound(0x192); +	stopSound(0x193); +	stopSound(0x196); +	stopSound(0x197); +	stopSound(0x198); +	stopSound(0x199); +	stopSound(0x19A); +} + +void GnapEngine::scene20_run() { +	 +	playSound(0x10940, 1); + +	startSoundTimerA(8); + +	_s20_stonerGuyShowingJoint = false; +	_timers[7] = getRandom(100) + 100; + +	_s20_stonerGuyCtr = (_s20_stonerGuyCtr + 1) % 3; +	switch (_s20_stonerGuyCtr) { +	case 1: +		_s20_currStonerGuySequenceId = 0x171; +		break; +	case 2: +		_s20_currStonerGuySequenceId = 0x172; +		break; +	case 3: +		_s20_currStonerGuySequenceId = 0x173; +		break; +	} +	 +	_s20_nextStonerGuySequenceId = -1; +	_gameSys->setAnimation(_s20_currStonerGuySequenceId, 21, 2); +	_gameSys->insertSequence(_s20_currStonerGuySequenceId, 21, 0, 0, kSeqNone, 0, 0, 0); +	 +	_timers[6] = getRandom(20) + 30; +	 +	_s20_currGroceryStoreGuySequenceId = 0x17C; +	_s20_nextGroceryStoreGuySequenceId = -1; +	_gameSys->setAnimation(0x17C, 20, 3);	 +	_gameSys->insertSequence(0x17C, 20, 0, 0, kSeqNone, 0, 0, 0); +	 +	_timers[5] = getRandom(50) + 130; +	if (isFlag(19)) +		_gameSys->insertSequence(0x17F, 20, 0, 0, kSeqNone, 0, 0, 0); +	else +		_gameSys->insertSequence(0x174, 20, 0, 0, kSeqNone, 0, 0, 0); +	 +	queueInsertDeviceIcon(); +	 +	if (isFlag(11)) { +		clearFlag(11); +		endSceneInit(); +		_gameSys->setAnimation(0x182, 140, 0); +		_gameSys->insertSequence(0x182, 140, 0, 0, kSeqNone, 0, 0, 0); +		while (_gameSys->getAnimationStatus(0) != 2) { +			// checkGameAppStatus(); +			gameUpdateTick(); +		} +		initGnapPos(11, 8, 3); +		initBeaverPos(11, 9, 4); +		gnapWalkTo(5, 8, -1, 0x107BA, 1); +		platypusWalkTo(6, 9, -1, 0x107C2, 1); +	} else { +		switch (_prevSceneNum) { +		case 17: +			initGnapPos(5, 11, 1); +			initBeaverPos(6, 11, 0); +			endSceneInit(); +			gnapWalkTo(5, 8, -1, 0x107B9, 1); +			platypusWalkTo(6, 9, -1, 0x107C2, 1); +			break; +		case 18: +			initGnapPos(11, 8, 3); +			initBeaverPos(11, 9, 4); +			endSceneInit(); +			gnapWalkTo(5, 8, -1, 0x107BA, 1); +			platypusWalkTo(6, 9, -1, 0x107C2, 1); +			break; +		case 21: +			initGnapPos(-1, 8, 3); +			initBeaverPos(-1, 9, 4); +			endSceneInit(); +			gnapWalkTo(3, 8, -1, 0x107B9, 1); +			platypusWalkTo(3, 9, -1, 0x107C2, 1); +			break; +		case 22: +			initGnapPos(7, 6, 1); +			initBeaverPos(8, 6, 0); +			endSceneInit(); +			gnapWalkTo(8, 8, -1, 0x107B9, 1); +			platypusWalkTo(9, 9, -1, 0x107C2, 1); +			break; +		default: +			initGnapPos(8, 6, 3); +			initBeaverPos(9, 6, 4); +			endSceneInit(); +			_hotspots[kHSWalkArea2].flags |= SF_WALKABLE; +			gnapWalkTo(8, 8, -1, 0x107BA, 1); +			platypusWalkTo(9, 9, -1, 0x107C2, 1); +			_hotspots[kHSWalkArea2].flags &= ~SF_WALKABLE; +			break; +		} +	} +	 +	while (!_sceneDone) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 0, -1, -1, -1, -1); +		testWalk(0, 1, 7, 9, 8, 9); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene20_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemJoint) { +					gnapUseJointOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(20); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSExitParkingLot: +			if (_gnapActionStatus < 0) { +				if (_s20_stonerGuyShowingJoint) +					_timers[4] = 0; +				_isLeavingScene = 1; +				_newSceneNum = 21; +				gnapWalkTo(_hotspotsWalkPos[kHSExitParkingLot].x, _hotspotsWalkPos[kHSExitParkingLot].y, 0, 0x107AF, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[kHSExitParkingLot].x, _hotspotsWalkPos[kHSExitParkingLot].y + 1, -1, 0x107CF, 1); +				_beaverFacing = 4; +			} +			break; +		 +		case kHSExitPhone: +			if (_gnapActionStatus < 0) { +				if (_s20_stonerGuyShowingJoint) +					_timers[4] = 0; +				_isLeavingScene = 1; +				_newSceneNum = 17; +				gnapWalkTo(_hotspotsWalkPos[kHSExitPhone].x, _hotspotsWalkPos[kHSExitPhone].y, 0, 0x107AE, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[kHSExitPhone].x + 1, _hotspotsWalkPos[kHSExitPhone].y, -1, 0x107C2, 1); +			} +			break; +		 +		case kHSExitOutsideToyStore: +			if (_gnapActionStatus < 0) { +				if (_s20_stonerGuyShowingJoint) +					_timers[4] = 0; +				_isLeavingScene = 1; +				_newSceneNum = 18; +				_hotspots[kHSWalkArea2].flags |= SF_WALKABLE; +				gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideToyStore].x, _hotspotsWalkPos[kHSExitOutsideToyStore].y, 0, 0x107AB, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideToyStore].x, _hotspotsWalkPos[kHSExitOutsideToyStore].y + 1, -1, 0x107CD, 1); +				_hotspots[kHSWalkArea2].flags &= ~SF_WALKABLE; +			} +			break; +		 +		case kHSExitInsideGrubCity: +			if (_gnapActionStatus < 0) { +				if (_s20_stonerGuyShowingJoint) +					_timers[4] = 0; +				_isLeavingScene = 1; +				_newSceneNum = 22; +				gnapWalkTo(_hotspotsWalkPos[kHSExitInsideGrubCity].x, _hotspotsWalkPos[kHSExitInsideGrubCity].y - 1, 0, 0x107BB, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[kHSExitInsideGrubCity].x + 1, _hotspotsWalkPos[kHSExitInsideGrubCity].y, -1, 0x107C2, 1); +				_beaverFacing = 4; +			} +			break; +		 +		case kHSExitOutsideCircusWorld: +			if (_gnapActionStatus < 0) { +				if (_s20_stonerGuyShowingJoint) +					_timers[4] = 0; +				_isLeavingScene = 1; +				_newSceneNum = 24; +				gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideCircusWorld].x, _hotspotsWalkPos[kHSExitOutsideCircusWorld].y, 0, 0x107BB, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideCircusWorld].x + 1, _hotspotsWalkPos[kHSExitOutsideCircusWorld].y, -1, 0x107C2, 1); +			} +			break; +		 +		case kHSStonerGuy: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSStonerGuy].x, _hotspotsWalkPos[kHSStonerGuy].y, 5, 4); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan2(5, 4); +						break; +					case GRAB_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(_hotspotsWalkPos[kHSStonerGuy].x, _hotspotsWalkPos[kHSStonerGuy].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +						if (_s20_stonerGuyShowingJoint) +							_gnapActionStatus = kASGrabJoint; +						else +							playGnapImpossible(0, 0); +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(_hotspotsWalkPos[kHSStonerGuy].x, _hotspotsWalkPos[kHSStonerGuy].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						if (isFlag(17)) +							_gnapActionStatus = kASTalkStonerGuyNoJoint; +						else +							_gnapActionStatus = kASTalkStonerGuyHasJoint; +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSGroceryStoreGuy: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSGroceryStoreGuy].x, _hotspotsWalkPos[kHSGroceryStoreGuy].y, 2, 4); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(2, 3); +						break; +					case GRAB_CURSOR: +						_s20_stonerGuyShowingJoint = false; +						_gnapIdleFacing = 5; +						gnapWalkTo(_hotspotsWalkPos[kHSGroceryStoreGuy].x, _hotspotsWalkPos[kHSGroceryStoreGuy].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASGrabGroceryStoreGuy; +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 5; +						gnapWalkTo(_hotspotsWalkPos[kHSGroceryStoreGuy].x, _hotspotsWalkPos[kHSGroceryStoreGuy].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASTalkGroceryStoreGuy; +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSGroceryStoreHat: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemCowboyHat) { +					_gnapIdleFacing = 7; +					gnapWalkTo(_hotspotsWalkPos[kHSGroceryStoreHat].x, _hotspotsWalkPos[kHSGroceryStoreHat].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +					_gnapActionStatus = kASSwitchGroceryStoreHat; +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSGroceryStoreHat].x, _hotspotsWalkPos[kHSGroceryStoreHat].y, 1, 6); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(1, 6); +						break; +					case GRAB_CURSOR: +						_s20_stonerGuyShowingJoint = false; +						_gnapIdleFacing = 5; +						gnapWalkTo(_hotspotsWalkPos[kHSGroceryStoreGuy].x, _hotspotsWalkPos[kHSGroceryStoreGuy].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASGrabGroceryStoreHat; +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSWalkArea1: +		case kHSWalkArea2: +			gnapWalkTo(-1, -1, -1, -1, 1); +			break; +		 +		default: +			if (_mouseClickState.left) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +		 +		} + +		scene20_updateAnimations(); + +		if (!isSoundPlaying(0x10940)) +			playSound(0x10940, 1); +	 +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0) { +				_hotspots[kHSWalkArea1].y2 += 48; +				updateBeaverIdleSequence(); +				_hotspots[kHSWalkArea1].y2 -= 48; +			} +			if (_gnapActionStatus < 0) +				updateGnapIdleSequence(); +			if (_gnapActionStatus < 0 && !_timers[5] && _s20_nextGroceryStoreGuySequenceId == -1) { +				_timers[5] = getRandom(50) + 130; +				if (getRandom(4) != 0) +					_s20_nextGroceryStoreGuySequenceId = 0x17C; +				else +					_s20_nextGroceryStoreGuySequenceId = 0x17A; +			} +			if (!_timers[7]) { +				_timers[7] = getRandom(100) + 100; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0) { +					switch (getRandom(3)) { +					case 0: +						_gameSys->insertSequence(0x183, 253, 0, 0, kSeqNone, 0, 0, 0); +						break; +					case 1: +						_gameSys->insertSequence(0x184, 253, 0, 0, kSeqNone, 0, 0, 0); +						break; +					case 2: +						_gameSys->insertSequence(0x185, 253, 0, 0, kSeqNone, 0, 0, 0); +						break; +					} +				} +			} +			playSoundA(); +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene20_updateHotspots(); +		} +		 +		gameUpdateTick(); +	 +	} +	 +} + +void GnapEngine::scene20_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASLeaveScene: +			_sceneDone = true; +			break; +		case kASTalkStonerGuyNoJoint: +			_gameSys->setAnimation(0x170, 21, 2); +			_gameSys->setAnimation(0x17B, 20, 3); +			_gameSys->insertSequence(0x17B, 20, _s20_currGroceryStoreGuySequenceId, 20, 32, 0, 0, 0); +			_gameSys->insertSequence(0x170, 21, _s20_currStonerGuySequenceId, 21, 32, 0, 0, 0); +			stopSound(0x1A1); +			scene20_stopSounds(); +			_s20_currGroceryStoreGuySequenceId = 0x17B; +			_s20_currStonerGuySequenceId = 0x170; +			_s20_nextGroceryStoreGuySequenceId = -1; +			_s20_nextStonerGuySequenceId = 0x16E; +			_timers[5] = 100; +			_timers[6] = 100; +			break; +		case kASTalkStonerGuyHasJoint: +			_gameSys->setAnimation(0x168, 21, 2); +			_gameSys->setAnimation(379, 20, 3); +			_gameSys->insertSequence(0x17B, 20, _s20_currGroceryStoreGuySequenceId, 20, 32, 0, 0, 0); +			_gameSys->insertSequence(0x170, 21, _s20_currStonerGuySequenceId, 21, 32, 0, 0, 0); +			_gameSys->insertSequence(0x168, 21, 0x170, 21, kSeqSyncWait, 0, 0, 0); +			stopSound(0x1A1); +			scene20_stopSounds(); +			_s20_currGroceryStoreGuySequenceId = 0x17B; +			_s20_currStonerGuySequenceId = 0x168; +			_s20_nextGroceryStoreGuySequenceId = -1; +			_s20_nextStonerGuySequenceId = 0x16B; +			_timers[5] = 200; +			_timers[6] = 200; +			_timers[4] = 100; +			_s20_stonerGuyShowingJoint = true; +			_gnapActionStatus = -1; +			break; +		case kASGrabJoint: +			_s20_nextStonerGuySequenceId = 0x16A; +			break; +		case kASActionDone: +			_gnapActionStatus = -1; +			break; +		case kASTalkGroceryStoreGuy: +			_gameSys->setAnimation(0x170, 21, 2); +			_gameSys->setAnimation(0x17B, 20, 3); +			_gameSys->insertSequence(0x17B, 20, _s20_currGroceryStoreGuySequenceId, 20, 32, 0, 0, 0); +			_gameSys->insertSequence(0x170, 21, _s20_currStonerGuySequenceId, 21, 32, 0, 0, 0); +			stopSound(0x1A1); +			scene20_stopSounds(); +			_s20_currGroceryStoreGuySequenceId = 0x17B; +			_s20_currStonerGuySequenceId = 0x170; +			_s20_groceryStoreGuyCtr = (_s20_groceryStoreGuyCtr + 1) % 2; +			if (_s20_groceryStoreGuyCtr != 0) +				_s20_nextGroceryStoreGuySequenceId = 0x176; +			else +				_s20_nextGroceryStoreGuySequenceId = 0x177; +			_timers[5] = 100; +			_timers[6] = 100; +			break; +		case kASGrabGroceryStoreGuy: +			_gameSys->setAnimation(0x170, 21, 2); +			_gameSys->setAnimation(0x17B, 20, 3); +			_gameSys->insertSequence(0x170, 21, _s20_currStonerGuySequenceId, 21, 32, 0, 0, 0); +			_gameSys->insertSequence(0x17B, 20, _s20_currGroceryStoreGuySequenceId, 20, 32, 0, 0, 0); +			stopSound(0x1A1); +			scene20_stopSounds(); +			_s20_currGroceryStoreGuySequenceId = 0x17B; +			_s20_currStonerGuySequenceId = 0x170; +			_timers[5] = 120; +			_timers[6] = 120; +			_s20_nextGroceryStoreGuySequenceId = 0x178; +			break; +		case kASGrabGroceryStoreHat: +			_gameSys->setAnimation(0x170, 21, 2); +			_gameSys->setAnimation(0x17B, 20, 3); +			_gameSys->insertSequence(0x17B, 20, _s20_currGroceryStoreGuySequenceId, 20, 32, 0, 0, 0); +			_gameSys->insertSequence(0x170, 21, _s20_currStonerGuySequenceId, 21, 32, 0, 0, 0); +			stopSound(0x1A1); +			scene20_stopSounds(); +			_s20_currGroceryStoreGuySequenceId = 0x17B; +			_s20_currStonerGuySequenceId = 0x170; +			_s20_nextGroceryStoreGuySequenceId = 0x179; +			break; +		case kASSwitchGroceryStoreHat: +			setGrabCursorSprite(-1); +			_gameSys->setAnimation(0x180, _gnapId, 0); +			_gameSys->insertSequence(0x180, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x180; +			_gnapSequenceDatNum = 0; +			invRemove(kItemCowboyHat); +			invAdd(kItemGroceryStoreHat); +			_gnapActionStatus = kASSwitchGroceryStoreHatDone; +			break; +		case kASSwitchGroceryStoreHatDone: +			_gameSys->insertSequence(0x17F, 20, 372, 20, kSeqSyncWait, 0, 0, 0); +			setFlag(19); +			hideCursor(); +			setGrabCursorSprite(-1); +			addFullScreenSprite(0x12C, 255); +			_gameSys->setAnimation(0x181, 256, 0); +			_gameSys->insertSequence(0x181, 256, 0, 0, kSeqNone, 0, 0, 0); +			while (_gameSys->getAnimationStatus(0) != 2) +				gameUpdateTick(); +			removeFullScreenSprite(); +			showCursor(); +			setGrabCursorSprite(kItemGroceryStoreHat); +			_gnapIdleFacing = 1; +			gnapWalkTo(3, 8, -1, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +			_gnapActionStatus = -1; +			break; +		case kASGrabJointDone: +			setGrabCursorSprite(kItemJoint); +			_gnapActionStatus = -1; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2) { +		switch (_s20_nextGroceryStoreGuySequenceId) { +		case 0x176: +		case 0x177: +			_gameSys->setAnimation(_s20_nextGroceryStoreGuySequenceId, 20, 3); +			_gameSys->insertSequence(_s20_nextGroceryStoreGuySequenceId, 20, _s20_currGroceryStoreGuySequenceId, 20, kSeqSyncWait, 0, 0, 0); +			_s20_currGroceryStoreGuySequenceId = _s20_nextGroceryStoreGuySequenceId; +			_s20_nextGroceryStoreGuySequenceId = -1; +			_s20_nextStonerGuySequenceId = 0x16D; +			break; +		case 0x178: +			_gameSys->setAnimation(_s20_nextGroceryStoreGuySequenceId, 20, 3); +			_gameSys->setAnimation(0x17D, _gnapId, 0); +			_gameSys->insertSequence(_s20_nextGroceryStoreGuySequenceId, 20, _s20_currGroceryStoreGuySequenceId, 20, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x17D, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x17D; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = kASActionDone; +			_gameSys->setAnimation(0x16D, 21, 2); +			_gameSys->insertSequence(0x16D, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0); +			_s20_currStonerGuySequenceId = 0x16D; +			_s20_currGroceryStoreGuySequenceId = 0x178; +			_s20_nextGroceryStoreGuySequenceId = -1; +			_s20_nextStonerGuySequenceId = -1; +			break; +		case 0x179: +			_gameSys->setAnimation(_s20_nextGroceryStoreGuySequenceId, 20, 3); +			_gameSys->setAnimation(0x16D, 21, 0); +			_gameSys->insertSequence(_s20_nextGroceryStoreGuySequenceId, 20, _s20_currGroceryStoreGuySequenceId, 20, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x17E, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x17E; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = kASActionDone; +			_gameSys->setAnimation(0x16D, 21, 2); +			_gameSys->insertSequence(0x16D, 21, _s20_currStonerGuySequenceId, 21, kSeqSyncWait, 0, 0, 0); +			_s20_currStonerGuySequenceId = 0x16D; +			_s20_currGroceryStoreGuySequenceId = 377; +			_s20_nextGroceryStoreGuySequenceId = -1; +			_s20_nextStonerGuySequenceId = -1; +			gnapWalkTo(4, 8, -1, 0x107BB, 1); +			break; +		case 0x17C: +			_gameSys->setAnimation(0, 0, 3); +			_s20_nextStonerGuySequenceId = 0x171; +			break; +		case 0x17A: +			_gameSys->setAnimation(0, 0, 3); +			_s20_nextStonerGuySequenceId = 0x16F; +			break; +		case 0x175: +			_gameSys->setAnimation(0x175, 20, 0); +			_gameSys->setAnimation(0x175, 20, 3); +			_gameSys->insertSequence(0x175, 20, _s20_currGroceryStoreGuySequenceId, 20, kSeqSyncWait, 0, 0, 0); +			_s20_currGroceryStoreGuySequenceId = 0x175; +			_s20_nextGroceryStoreGuySequenceId = -1; +			_gnapActionStatus = kASActionDone; +			break; +		default: +			if (_s20_nextGroceryStoreGuySequenceId != -1) { +				_gameSys->setAnimation(_s20_nextGroceryStoreGuySequenceId, 20, 3); +				_gameSys->insertSequence(_s20_nextGroceryStoreGuySequenceId, 20, _s20_currGroceryStoreGuySequenceId, 20, kSeqSyncWait, 0, 0, 0); +				_s20_currGroceryStoreGuySequenceId = _s20_nextGroceryStoreGuySequenceId; +				_s20_nextGroceryStoreGuySequenceId = -1; +			} +			break; +		} +	} +	 +	scene20_updateAnimationsCb(); + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene21.cpp b/engines/gnap/scenes/scene21.cpp new file mode 100644 index 0000000000..56da904ce1 --- /dev/null +++ b/engines/gnap/scenes/scene21.cpp @@ -0,0 +1,345 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus				= 0, +	kHSBanana				= 1, +	kHSOldLady				= 2, +	kHSDevice				= 3, +	kHSExitOutsideGrubCity	= 4, +	kHSWalkArea1			= 5, +	kHSWalkArea2			= 6 +}; + +enum { +	kASTalkOldLady				= 0, +	kASGrabBanana				= 1, +	kASGrabBananaDone			= 2, +	kASGrabOldLady				= 3, +	kASUseHatWithOldLady		= 4, +	kASUseHatWithOldLadyDone	= 5, +	kASLeaveScene				= 6 +}; + +int GnapEngine::scene21_init() { +	_gameSys->setAnimation(0, 0, 3); +	return isFlag(3) ? 0x94 : 0x93; +} + +void GnapEngine::scene21_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSBanana, 94, 394, 146, 430, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 2, 6); +	setHotspot(kHSOldLady, 402, 220, 528, 430, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 4, 7); +	setHotspot(kHSExitOutsideGrubCity, 522, 498, 800, 600, SF_EXIT_SE_CURSOR | SF_WALKABLE, 5, 10); +	setHotspot(kHSWalkArea1, 0, 0, 800, 440); +	setHotspot(kHSWalkArea2, 698, 0, 800, 600); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	if (isFlag(4) || !isFlag(3)) +		_hotspots[kHSBanana].flags = SF_WALKABLE | SF_DISABLED; +	if (isFlag(3)) +		_hotspots[kHSOldLady].flags = SF_DISABLED; +	_hotspotsCount = 7; +} + +void GnapEngine::scene21_run() { + +	playSound(0x10940, 1); +	startSoundTimerA(6); +	 +	_timers[5] = getRandom(100) + 100; +	 +	queueInsertDeviceIcon(); +	 +	if (isFlag(3)) { +		if (isFlag(5)) { +			initGnapPos(5, 8, 1); +			initBeaverPos(6, 8, 0); +			_gameSys->insertSequence(0x8E, 2, 0, 0, kSeqNone, 0, 0, 0); +			if (!isFlag(4)) +				_gameSys->insertSequence(0x8D, 59, 0, 0, kSeqNone, 0, 0, 0); +			endSceneInit(); +			clearFlag(5); +		} else { +			initGnapPos(5, 11, 1); +			initBeaverPos(6, 11, 0); +			if (!isFlag(4)) +				_gameSys->insertSequence(0x8D, 59, 0, 0, kSeqNone, 0, 0, 0); +			endSceneInit(); +			gnapWalkTo(5, 8, -1, 0x107B9, 1); +			platypusWalkTo(6, 8, -1, 0x107C2, 1); +		} +	} else { +		initGnapPos(5, 11, 1); +		initBeaverPos(6, 11, 0); +		_s21_currOldLadySequenceId = 0x89; +		_gameSys->setAnimation(0x89, 79, 3); +		_gameSys->insertSequence(_s21_currOldLadySequenceId, 79, 0, 0, kSeqNone, 0, 0, 0); +		_s21_nextOldLadySequenceId = -1; +		_timers[4] = getRandom(30) + 50; +		endSceneInit(); +		gnapWalkTo(5, 8, -1, 0x107B9, 1); +		platypusWalkTo(6, 8, -1, 0x107C2, 1); +	} +	 +	while (!_sceneDone) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); + +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene21_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemJoint) { +					gnapUseJointOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSBanana: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowItem(_grabCursorSpriteIndex, 2, 5); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(2, 5); +						break; +					case GRAB_CURSOR: +						gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, _hotspotsWalkPos[kHSBanana].x, _hotspotsWalkPos[kHSBanana].y) | 0x10000, 1); +						playGnapPullOutDevice(2, 5); +						playGnapUseDevice(0, 0); +						_gnapActionStatus = kASGrabBanana; +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						break; +					} +				} +			} +			break; + +		case kHSOldLady: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemGroceryStoreHat) { +					_newSceneNum = 47; +					gnapWalkTo(4, 6, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +					_gnapActionStatus = kASUseHatWithOldLady; +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(4, 6, 7, 4); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(7, 4); +						break; +					case GRAB_CURSOR: +						_gnapIdleFacing = 5; +						_hotspots[kHSWalkArea1].flags |= SF_WALKABLE; +						gnapWalkTo(7, 6, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASGrabOldLady; +						_hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE; +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(_hotspotsWalkPos[kHSOldLady].x, _hotspotsWalkPos[kHSOldLady].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASTalkOldLady; +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSExitOutsideGrubCity: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				_newSceneNum = 20; +				gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideGrubCity].x, _hotspotsWalkPos[kHSExitOutsideGrubCity].y, 0, 0x107B3, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideGrubCity].x + 1, _hotspotsWalkPos[kHSExitOutsideGrubCity].y, -1, 0x107C2, 1); +			} +			break; +		 +		case kHSWalkArea1: +		case kHSWalkArea2: +			gnapWalkTo(-1, -1, -1, -1, 1); +			break; +		 +		default: +			if (_mouseClickState.left) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +		 +		} +	 +		scene21_updateAnimations(); +	 +		if (!isSoundPlaying(0x10940)) +			playSound(0x10940, 1); +	 +		if (!_isLeavingScene) { +			updateBeaverIdleSequence(); +			updateGnapIdleSequence(); +			if (!isFlag(3) && !_timers[4] && _s21_nextOldLadySequenceId == -1 && _gnapActionStatus == -1) { +				_timers[4] = getRandom(30) + 50; +				switch (getRandom(5)) { +				case 0: +					_s21_nextOldLadySequenceId = 0x88; +					break; +				case 1: +					_s21_nextOldLadySequenceId = 0x8A; +					break; +				default: +					_s21_nextOldLadySequenceId = 0x89; +					break; +				} +			} +			if (!_timers[5]) { +				_timers[5] = getRandom(100) + 100; +				_gameSys->insertSequence(0x92, 255, 0, 0, kSeqNone, 0, 0, 0); +			} +			playSoundA(); +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene21_updateHotspots(); +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene21_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASTalkOldLady: +			_s21_nextOldLadySequenceId = 0x8B; +			_gnapActionStatus = -1; +			break; +		case kASGrabBanana: +			_gameSys->setAnimation(0x8C, 59, 0); +			_gameSys->insertSequence(0x8C, 59, 141, 59, kSeqSyncWait, 0, 0, 0); +			setFlag(4); +			invAdd(kItemBanana); +			scene21_updateHotspots(); +			_gnapActionStatus = kASGrabBananaDone; +			break; +		case kASGrabBananaDone: +			setGrabCursorSprite(kItemBanana); +			_gnapActionStatus = -1; +			break; +		case kASGrabOldLady: +			_timers[4] = getRandom(30) + 50; +			_s21_nextOldLadySequenceId = 0x87; +			break; +		case kASUseHatWithOldLady: +			_gameSys->setAnimation(0x8F, _gnapId, 0); +			_gameSys->insertSequence(0x8F, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x8F; +			_gnapActionStatus = kASUseHatWithOldLadyDone; +			invAdd(kItemTickets); +			invRemove(kItemGroceryStoreHat); +			setGrabCursorSprite(-1); +			break; +		case kASUseHatWithOldLadyDone: +			_s21_nextOldLadySequenceId = 0x91; +			break; +		case kASLeaveScene: +			_sceneDone = true; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2 && _s21_nextOldLadySequenceId != -1) { +		if (_s21_nextOldLadySequenceId == 0x87) { +			_gameSys->setAnimation(_s21_nextOldLadySequenceId, 79, 3); +			_gameSys->insertSequence(_s21_nextOldLadySequenceId, 79, _s21_currOldLadySequenceId, 79, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x86, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x86; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = -1; +			_s21_currOldLadySequenceId = _s21_nextOldLadySequenceId; +			_s21_nextOldLadySequenceId = -1; +		} else if (_s21_nextOldLadySequenceId == 0x91) { +			_gameSys->setAnimation(0x91, 79, 0); +			_gameSys->insertSequence(_s21_nextOldLadySequenceId, 79, _s21_currOldLadySequenceId, 79, kSeqSyncWait, 0, 0, 0); +			_gnapActionStatus = kASLeaveScene; +			_s21_currOldLadySequenceId = _s21_nextOldLadySequenceId; +			_s21_nextOldLadySequenceId = -1; +		} else { +			_gameSys->setAnimation(_s21_nextOldLadySequenceId, 79, 3); +			_gameSys->insertSequence(_s21_nextOldLadySequenceId, 79, _s21_currOldLadySequenceId, 79, kSeqSyncWait, 0, 0, 0); +			_s21_currOldLadySequenceId = _s21_nextOldLadySequenceId; +			_s21_nextOldLadySequenceId = -1; +		} +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene22.cpp b/engines/gnap/scenes/scene22.cpp new file mode 100644 index 0000000000..0290666daa --- /dev/null +++ b/engines/gnap/scenes/scene22.cpp @@ -0,0 +1,294 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus				= 0, +	kHSExitOutsideGrubCity	= 1, +	kHSExitBackGrubCity		= 2, +	kHSCashier				= 3, +	kHSDevice				= 4, +	kHSWalkArea1			= 5, +	kHSWalkArea2			= 6 +}; + +enum { +	kASLeaveScene				= 0, +	kASTalkCashier				= 1 +}; + +int GnapEngine::scene22_init() { +	return 0x5E; +} + +void GnapEngine::scene22_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitOutsideGrubCity, 0, 180, 184, 472, SF_EXIT_L_CURSOR, 3, 6); +	setHotspot(kHSExitBackGrubCity, 785, 405, 800, 585, SF_EXIT_R_CURSOR, 11, 9); +	setHotspot(kHSCashier, 578, 230, 660, 376, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 8); +	setHotspot(kHSWalkArea1, 553, 0, 800, 542); +	setHotspot(kHSWalkArea2, 0, 0, 552, 488); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 7; +} + +void GnapEngine::scene22_run() { + +	_gameSys->insertSequence(0x5D, 254, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s22_currCashierSequenceId = 0x59; +	_s22_nextCashierSequenceId = -1; +	 +	_gameSys->setAnimation(0x59, 1, 3); +	_gameSys->insertSequence(_s22_currCashierSequenceId, 1, 0, 0, kSeqNone, 0, 0, 0); +	 +	_timers[6] = getRandom(30) + 20; +	 +	queueInsertDeviceIcon(); +	 +	if (_prevSceneNum == 20) { +		initGnapPos(2, 8, 1); +		initBeaverPos(1, 8, 0); +		endSceneInit(); +	} else { +		initGnapPos(11, _hotspotsWalkPos[kHSExitBackGrubCity].y, 1); +		initBeaverPos(11, _hotspotsWalkPos[kHSExitBackGrubCity].y + 1, 0); +		endSceneInit(); +		gnapWalkTo(8, 8, -1, 0x107B9, 1); +		platypusWalkTo(9, 8, -1, 0x107C2, 1); +	} +	 +	if (isFlag(11)) { +		int storeDetectiveSeqId; +		setGrabCursorSprite(-1); +		invRemove(kItemCereals); +		if (_s22_caughtBefore) { +			switch (getRandom(3)) { +			case 0: +				storeDetectiveSeqId = 0x55; +				break; +			case 1: +				storeDetectiveSeqId = 0x56; +				break; +			case 2: +				storeDetectiveSeqId = 0x57; +				break; +			} +		} else { +			_s22_caughtBefore = true; +			storeDetectiveSeqId = 0x54; +		} +		_gameSys->waitForUpdate(); +		_gameSys->requestClear1(); +		_gameSys->drawSpriteToBackground(0, 0, 0x44); +		_gameSys->setAnimation(storeDetectiveSeqId, 256, 4); +		_gameSys->insertSequence(storeDetectiveSeqId, 256, 0, 0, kSeqNone, 0, 0, 0); +		while (_gameSys->getAnimationStatus(4) != 2) { +			gameUpdateTick(); +		} +		_sceneDone = true; +		_newSceneNum = 20; +		_s22_caughtBefore = true; +	} +	 +	while (!_sceneDone) { +		 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 0, -1, -1, -1, -1); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene22_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemJoint) { +					gnapUseJointOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSExitOutsideGrubCity: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				_newSceneNum = 20; +				gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideGrubCity].x, _hotspotsWalkPos[kHSExitOutsideGrubCity].y, 0, 0x107AF, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideGrubCity].x, _hotspotsWalkPos[kHSExitOutsideGrubCity].y + 1, -1, 0x107C2, 1); +			} +			break; + +		case kHSExitBackGrubCity: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				_newSceneNum = 23; +				gnapWalkTo(_hotspotsWalkPos[kHSExitBackGrubCity].x, _hotspotsWalkPos[kHSExitBackGrubCity].y, 0, 0x107AB, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[kHSExitBackGrubCity].x, _hotspotsWalkPos[kHSExitBackGrubCity].y + 1, -1, 0x107C2, 1); +			} +			break; +		 +		case kHSCashier: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSCashier].x, _hotspotsWalkPos[kHSCashier].y, 8, 4); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(8, 4); +						break; +					case GRAB_CURSOR: +						playGnapImpossible(0, 0); +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(_hotspotsWalkPos[kHSCashier].x, _hotspotsWalkPos[kHSCashier].y, +							0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASTalkCashier; +						break; +					case PLAT_CURSOR: +						gnapUseDeviceOnBeaver(); +						break; +					} +				} +			} +			break; +		 +		case kHSWalkArea1: +		case kHSWalkArea2: +			gnapWalkTo(-1, -1, -1, -1, 1); +			break; +		 +		default: +			if (_mouseClickState.left) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +		 +		} +	 +		scene22_updateAnimations(); +	 +		if (!_isLeavingScene) { +			updateBeaverIdleSequence(); +			updateGnapIdleSequence(); +			if (!_timers[6] && _s22_nextCashierSequenceId == -1) { +				_timers[6] = getRandom(30) + 20; +				if (getRandom(8) != 0) { +					_s22_nextCashierSequenceId = 0x59; +				} else { +					_s22_cashierCtr = (_s22_cashierCtr + 1) % 3; +					switch (_s22_cashierCtr) { +					case 1: +						_s22_nextCashierSequenceId = 0x58; +						break; +					case 2: +						_s22_nextCashierSequenceId = 0x5A; +						break; +					case 3: +						_s22_nextCashierSequenceId = 0x5B; +						break; +					default: +						_s22_nextCashierSequenceId = 0x58; +						break; +					} +				} +			} +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene22_updateHotspots(); +			_timers[2] = getRandom(30) + 20; +			_timers[3] = 400; +			_timers[1] = getRandom(20) + 30; +			_timers[0] = getRandom(75) + 75; +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene22_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASLeaveScene: +			_sceneDone = true; +			break; +		case kASTalkCashier: +			_s22_nextCashierSequenceId = 0x5C; +			break; +		} +		_gnapActionStatus = -1; +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2 && _s22_nextCashierSequenceId != -1) { +		_gameSys->setAnimation(_s22_nextCashierSequenceId, 1, 3); +		_gameSys->insertSequence(_s22_nextCashierSequenceId, 1, _s22_currCashierSequenceId, 1, kSeqSyncWait, 0, 0, 0); +		_s22_currCashierSequenceId = _s22_nextCashierSequenceId; +		_s22_nextCashierSequenceId = -1; +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene23.cpp b/engines/gnap/scenes/scene23.cpp new file mode 100644 index 0000000000..cafeb71a56 --- /dev/null +++ b/engines/gnap/scenes/scene23.cpp @@ -0,0 +1,297 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus				= 0, +	kHSExitFrontGrubCity	= 1, +	kHSDevice				= 2, +	kHSCereals				= 3, +	kHSWalkArea1			= 4, +	kHSWalkArea2			= 5 +}; + +enum { +	kASLookCereals			= 0, +	kASGrabCereals			= 1, +	kASGrabCerealsDone		= 2, +	kASLeaveScene			= 3 +}; + +int GnapEngine::scene23_init() { +	return 0xC0; +} + +void GnapEngine::scene23_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitFrontGrubCity, 0, 250, 15, 550, SF_EXIT_L_CURSOR | SF_WALKABLE, 0, 7); +	setHotspot(kHSCereals, 366, 332, 414, 408, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 4, 7); +	setHotspot(kHSWalkArea1, 0, 0, 340, 460); +	setHotspot(kHSWalkArea2, 340, 0, 800, 501); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 6; +} + +void GnapEngine::scene23_run() { +	 +	_timers[4] = getRandom(100) + 200; +	_timers[5] = getRandom(100) + 200; +	 +	_s23_currStoreClerkSequenceId = 0xB4; +	_s23_nextStoreClerkSequenceId = -1; +	 +	_gameSys->setAnimation(0xB4, 1, 4); +	_gameSys->insertSequence(_s23_currStoreClerkSequenceId, 1, 0, 0, kSeqNone, 0, 0, 0); +	 +	queueInsertDeviceIcon(); +	 +	initGnapPos(-1, 7, 1); +	initBeaverPos(-2, 7, 0); +	_gameSys->insertSequence(0xBD, 255, 0, 0, kSeqNone, 0, 0, 0); +	_gameSys->insertSequence(0xBF, 2, 0, 0, kSeqNone, 0, 0, 0); +	endSceneInit(); +	 +	platypusWalkTo(1, 7, -1, 0x107C2, 1); + +	if (isFlag(24)) { +		gnapWalkTo(2, 7, -1, 0x107B9, 1); +	} else { +		gnapWalkTo(2, 7, 0, 0x107B9, 1); +		while (_gameSys->getAnimationStatus(0) != 2) +			gameUpdateTick(); +		playSequences(0x48, 0xBA, 0xBB, 0xBC); +		setFlag(24); +	} +	 +	while (!_sceneDone) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 3, -1, -1, -1, -1); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene23_updateHotspots(); +			} +			break; +		 +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemJoint) { +					gnapUseJointOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSCereals: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSCereals].x, _hotspotsWalkPos[kHSCereals].y, 5, 4); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						if (isFlag(11)) +							playGnapMoan2(0, 0); +						else { +							gnapWalkTo(_hotspotsWalkPos[kHSCereals].x, _hotspotsWalkPos[kHSCereals].y, +								0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +							_gnapActionStatus = kASLookCereals; +						} +						break; +					case GRAB_CURSOR: +						if (isFlag(11)) +							playGnapImpossible(0, 0); +						else { +							_gnapIdleFacing = 1; +							gnapWalkTo(_hotspotsWalkPos[kHSCereals].x, _hotspotsWalkPos[kHSCereals].y, +								0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +							setFlag(11); +							_gnapActionStatus = kASGrabCereals; +							invAdd(kItemCereals); +						} +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSExitFrontGrubCity: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				_newSceneNum = 22; +				gnapWalkTo(_hotspotsWalkPos[kHSExitFrontGrubCity].x, _hotspotsWalkPos[kHSExitFrontGrubCity].y, 0, 0x107AF, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[kHSExitFrontGrubCity].x, _hotspotsWalkPos[kHSExitFrontGrubCity].y - 1, -1, 0x107C2, 1); +			} +			break; +		 +		case kHSWalkArea1: +		case kHSWalkArea2: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; +		 +		default: +			if (_mouseClickState.left) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +		 +		} +	 +		scene23_updateAnimations(); +	 +		if (!_isLeavingScene) { +			updateBeaverIdleSequence(); +			updateGnapIdleSequence(); +			if (!_timers[4] && _gnapActionStatus == -1) { +				_timers[4] = getRandom(100) + 200; +				switch (getRandom(4)) { +				case 0: +					_gameSys->insertSequence(0xB7, 256, 0, 0, kSeqNone, 0, 0, 0); +					break; +				case 1: +					_gameSys->insertSequence(0xB8, 256, 0, 0, kSeqNone, 0, 0, 0); +					break; +				case 2: +				case 3: +					_gameSys->insertSequence(0xB9, 256, 0, 0, kSeqNone, 0, 0, 0); +					break; +				} +			} +			if (!_timers[5]) { +				_timers[5] = getRandom(100) + 200; +				switch (getRandom(3)) { +				case 0: +					playSound(0xCE, 0); +					break; +				case 1: +					playSound(0xD0, 0); +					break; +				case 2: +					playSound(0xCF, 0); +					break; +				} +			} +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene23_updateHotspots(); +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene23_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASLookCereals: +			showFullScreenSprite(0x48); +			_gnapActionStatus = -1; +			break; +		case kASGrabCereals: +			_gameSys->setAnimation(0xBE, _gnapId, 0); +			_gameSys->insertSequence(0xBE, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->requestRemoveSequence(0xBF, 2); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0xBE; +			_gnapActionStatus = kASGrabCerealsDone; +			break; +		case kASGrabCerealsDone: +			setGrabCursorSprite(kItemCereals); +			_gnapActionStatus = -1; +			break; +		case kASLeaveScene: +			_sceneDone = true; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(4) == 2 && _s23_nextStoreClerkSequenceId == -1) { +		switch (getRandom(8)) { +		case 0: +		case 1: +		case 2: +			_s23_nextStoreClerkSequenceId = 0xB4; +			break; +		case 3: +		case 4: +		case 5: +			_s23_nextStoreClerkSequenceId = 0xB5; +			break; +		default: +			_s23_nextStoreClerkSequenceId = 0xB6; +			break; +		} +		_gameSys->setAnimation(_s23_nextStoreClerkSequenceId, 1, 4); +		_gameSys->insertSequence(_s23_nextStoreClerkSequenceId, 1, _s23_currStoreClerkSequenceId, 1, kSeqSyncWait, 0, 0, 0); +		_s23_currStoreClerkSequenceId = _s23_nextStoreClerkSequenceId; +		_s23_nextStoreClerkSequenceId = -1; +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene24.cpp b/engines/gnap/scenes/scene24.cpp new file mode 100644 index 0000000000..236ee7d30a --- /dev/null +++ b/engines/gnap/scenes/scene24.cpp @@ -0,0 +1,261 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus				= 0, +	kHSExitCircusWorld		= 1, +	kHSExitOutsideGrubCity	= 2, +	kHSDevice				= 3, +	kHSWalkArea1			= 4, +	kHSWalkArea2			= 5, +	kHSWalkArea3			= 6 +}; + +enum { +	kASLeaveScene			= 0 +}; + +int GnapEngine::scene24_init() { +	return 0x3B; +} + +void GnapEngine::scene24_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitCircusWorld, 785, 128, 800, 600, SF_EXIT_R_CURSOR, 8, 7); +	setHotspot(kHSExitOutsideGrubCity, 0, 213, 91, 600, SF_EXIT_NW_CURSOR, 1, 8); +	setHotspot(kHSWalkArea1, 0, 0, 0, 0); +	setHotspot(kHSWalkArea2, 530, 0, 800, 600); +	setHotspot(kHSWalkArea3, 0, 0, 800, 517); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 7; +} + +void GnapEngine::scene24_run() { +	int counter = 0; +	 +	playSound(0x10940, 1); +	 +	startSoundTimerA(9); +	 +	_timers[7] = getRandom(100) + 100; +	 +	_gameSys->insertSequence(0x2F, 256, 0, 0, kSeqNone, 0, 0, 0); +	 +	_timers[4] = getRandom(20) + 50; +	_timers[5] = getRandom(20) + 40; +	_timers[6] = getRandom(50) + 30; +	 +	_gameSys->insertSequence(0x36, 20, 0, 0, kSeqNone, 0, 0, 0); +	_gameSys->insertSequence(0x30, 20, 0, 0, kSeqNone, 0, 0, 0); +	_gameSys->insertSequence(0x35, 20, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s24_currWomanSequenceId = 0x35; +	_s24_girlSequenceId = 0x36; +	_s24_boySequenceId = 0x30; +	 +	if (_debugLevel == 4) +		startIdleTimer(8); +	 +	queueInsertDeviceIcon(); +	 +	if (_prevSceneNum == 20) { +		initGnapPos(1, 8, 1); +		initBeaverPos(2, 8, 0); +		endSceneInit(); +		gnapWalkTo(1, 9, -1, 0x107B9, 1); +		platypusWalkTo(2, 9, -1, 0x107C2, 1); +	} else { +		initGnapPos(8, 8, 3); +		initBeaverPos(8, 8, 4); +		endSceneInit(); +		gnapWalkTo(2, 8, -1, 0x107BA, 1); +		platypusWalkTo(3, 8, -1, 0x107C2, 1); +	} +	 +	while (!_sceneDone) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 0, -1, -1, -1, -1); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene24_updateHotspots(); +			} +			break; +		 +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemJoint) { +					gnapUseJointOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSExitCircusWorld: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				_newSceneNum = 25; +				gnapWalkTo(_hotspotsWalkPos[kHSExitCircusWorld].x, _hotspotsWalkPos[kHSExitCircusWorld].y, 0, 0x107AB, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[kHSExitCircusWorld].x + 1, _hotspotsWalkPos[kHSExitCircusWorld].y, -1, 0x107C2, 1); +			} +			break; +		 +		case kHSExitOutsideGrubCity: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				_newSceneNum = 20; +				_gnapIdleFacing = 7; +				gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideGrubCity].x, _hotspotsWalkPos[kHSExitOutsideGrubCity].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideGrubCity].x + 1, _hotspotsWalkPos[kHSExitOutsideGrubCity].y, -1, 0x107C2, 1); +			} +			break; +		 +		case kHSWalkArea1: +		case kHSWalkArea2: +		case kHSWalkArea3: +			if (_gnapActionStatus == -1) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; +		 +		default: +			if (_mouseClickState.left) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +		 +		} +	 +		scene24_updateAnimations(); +	 +		if (!isSoundPlaying(0x10940)) +			playSound(0x10940, 1); +	 +		if (!_isLeavingScene) { +			updateBeaverIdleSequence(); +			updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = getRandom(20) + 50; +				_gameSys->insertSequence(0x37, 20, _s24_girlSequenceId, 20, kSeqSyncWait, 0, 0, 0); +				_s24_girlSequenceId = 0x37; +			} +			if (!_timers[5]) { +				_timers[5] = getRandom(20) + 40; +				_gameSys->insertSequence(0x31, 20, _s24_boySequenceId, 20, kSeqSyncWait, 0, 0, 0); +				_s24_boySequenceId = 0x31; +			} +			if (!_timers[6]) { +				_timers[6] = getRandom(50) + 30; +				counter = (counter + 1) % 3; +				switch (counter) { +				case 0: +					_s24_nextWomanSequenceId = 0x32; +					break; +				case 1: +					_s24_nextWomanSequenceId = 0x33; +					break; +				case 2: +					_s24_nextWomanSequenceId = 0x34; +					break; +				} +				_gameSys->insertSequence(_s24_nextWomanSequenceId, 20, _s24_currWomanSequenceId, 20, kSeqSyncWait, 0, 0, 0); +				_s24_currWomanSequenceId = _s24_nextWomanSequenceId; +			} +			if (!_timers[7]) { +				_timers[7] = getRandom(100) + 100; +				switch (getRandom(3)) { +				case 0: +					_gameSys->insertSequence(0x38, 253, 0, 0, kSeqNone, 0, 0, 0); +					break; +				case 1: +					_gameSys->insertSequence(0x39, 253, 0, 0, kSeqNone, 0, 0, 0); +					break; +				case 2: +					_gameSys->insertSequence(0x3A, 253, 0, 0, kSeqNone, 0, 0, 0); +					break; +				} +			} +			if (_debugLevel == 4) +				updateIdleTimer(); +			playSoundA(); +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene24_updateHotspots(); +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene24_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		if (_gnapActionStatus == kASLeaveScene) +			_sceneDone = true; +		_gnapActionStatus = -1; +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene25.cpp b/engines/gnap/scenes/scene25.cpp new file mode 100644 index 0000000000..cb82658cc2 --- /dev/null +++ b/engines/gnap/scenes/scene25.cpp @@ -0,0 +1,401 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus					= 0, +	kHSTicketVendor				= 1, +	kHSExitOutsideCircusWorld	= 2, +	kHSExitInsideCircusWorld	= 3, +	kHSDevice					= 4, +	kHSPosters1					= 5, +	kHSPosters2					= 6, +	kHSPosters3					= 7, +	kHSPosters4					= 8, +	kHSWalkArea1				= 9, +	kHSWalkArea2				= 10 +}; + +enum { +	kASTalkTicketVendor				= 0, +	kASEnterCircusWihoutTicket		= 1, +	kASShowTicketToVendor			= 2, +	kASShowTicketToVendorDone		= 3, +	kASEnterCircusWihoutTicketDone	= 4, +	kASLeaveScene					= 5 +}; + +int GnapEngine::scene25_init() { +	return 0x62; +} + +void GnapEngine::scene25_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSTicketVendor, 416, 94, 574, 324, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 5, 5); +	setHotspot(kHSExitOutsideCircusWorld, 0, 519, 205, 600, SF_EXIT_SW_CURSOR, 5, 10); +	setHotspot(kHSExitInsideCircusWorld, 321, 70, 388, 350, SF_EXIT_NE_CURSOR, 3, 6); +	setHotspot(kHSPosters1, 0, 170, 106, 326, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 1, 7); +	setHotspot(kHSPosters2, 146, 192, 254, 306, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 7); +	setHotspot(kHSPosters3, 606, 162, 654, 368, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 7); +	setHotspot(kHSPosters4, 708, 114, 754, 490, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 8); +	setHotspot(kHSWalkArea1, 0, 0, 800, 439); +	setHotspot(kHSWalkArea2, 585, 0, 800, 600); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 11; +} + +void GnapEngine::scene25_playAnims(int index) { +	 +	if (index > 4) +		return; + +	hideCursor(); +	setGrabCursorSprite(-1); +	switch (index) { +	case 1: +		_largeSprite = _gameSys->createSurface(0x25); +		break; +	case 2: +		_largeSprite = _gameSys->createSurface(0x26); +		break; +	case 3: +		_largeSprite = _gameSys->createSurface(0x27); +		break; +	case 4: +		_largeSprite = _gameSys->createSurface(0x28); +		break; +	} +	_gameSys->insertSpriteDrawItem(_largeSprite, 0, 0, 300); +	delayTicksCursor(5); +	while (!_mouseClickState.left && !isKeyStatus1(Common::KEYCODE_ESCAPE) && !isKeyStatus1(Common::KEYCODE_SPACE) && +		!isKeyStatus1(29)) { +		gameUpdateTick(); +	} +	_mouseClickState.left = false; +	clearKeyStatus1(Common::KEYCODE_ESCAPE); +	clearKeyStatus1(29); +	clearKeyStatus1(Common::KEYCODE_SPACE); +	_gameSys->removeSpriteDrawItem(_largeSprite, 300); +	delayTicksCursor(5); +	deleteSurface(&_largeSprite); +	showCursor(); +} + +void GnapEngine::scene25_run() { + +	playSound(0x10940, 1); +	 +	startSoundTimerA(5); +	 +	_s25_currTicketVendorSequenceId = 0x52; +	_gameSys->setAnimation(0x52, 39, 3); +	_gameSys->insertSequence(_s25_currTicketVendorSequenceId, 39, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s25_nextTicketVendorSequenceId = -1; +	_timers[4] = getRandom(20) + 20; +	 +	queueInsertDeviceIcon(); +	 +	if (_prevSceneNum == 24) { +		initGnapPos(5, 11, 5); +		initBeaverPos(6, 11, 4); +		endSceneInit(); +		gnapWalkTo(5, 7, -1, 0x107BA, 1); +		platypusWalkTo(6, 7, -1, 0x107C2, 1); +	} else { +		initGnapPos(5, 6, 1); +		initBeaverPos(6, 6, 0); +		endSceneInit(); +		gnapWalkTo(5, 8, -1, 0x107B9, 1); +		platypusWalkTo(6, 8, -1, 0x107C2, 1); +	} +	 +	while (!_sceneDone) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene25_updateHotspots(); +			} +			break; +		 +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemJoint) { +					gnapUseJointOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSTicketVendor: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemTickets) { +					_gnapActionStatus = kASShowTicketToVendor; +					gnapWalkTo(_hotspotsWalkPos[kHSTicketVendor].x, _hotspotsWalkPos[kHSTicketVendor].y, +						0, getGnapSequenceId(gskIdle, 9, 4) | 0x10000, 1); +					playGnapPullOutDevice(0, 0); +					playGnapUseDevice(0, 0); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSTicketVendor].x, _hotspotsWalkPos[kHSTicketVendor].y, 6, 1); +					_s25_nextTicketVendorSequenceId = 0x5B; +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(6, 1); +						_s25_nextTicketVendorSequenceId = (getRandom(2) == 1) ? 0x59 : 0x56; +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(_hotspotsWalkPos[kHSTicketVendor].x, _hotspotsWalkPos[kHSTicketVendor].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASTalkTicketVendor; +						break; +					case GRAB_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSExitOutsideCircusWorld: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				_newSceneNum = 24; +				gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideCircusWorld].x, _hotspotsWalkPos[kHSExitOutsideCircusWorld].y, 0, 0x107B4, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideCircusWorld].x + 1, _hotspotsWalkPos[kHSExitOutsideCircusWorld].y, -1, 0x107C2, 1); +			} +			break; +		 +		case kHSExitInsideCircusWorld: +			if (_gnapActionStatus < 0) { +				if (isFlag(2)) { +					_isLeavingScene = true; +					_newSceneNum = 26; +					_hotspots[kHSWalkArea1].flags |= SF_WALKABLE; +					gnapWalkTo(_hotspotsWalkPos[kHSExitInsideCircusWorld].x, _hotspotsWalkPos[kHSExitInsideCircusWorld].y, 0, 0x107B1, 1); +					_gnapActionStatus = kASLeaveScene; +					platypusWalkTo(_hotspotsWalkPos[kHSExitInsideCircusWorld].x + 1, _hotspotsWalkPos[kHSExitInsideCircusWorld].y, -1, 0x107C2, 1); +					_hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE; +				} else { +					_hotspots[kHSWalkArea1].flags |= SF_WALKABLE; +					gnapWalkTo(4, 5, 0, 0x107BB, 1); +					_gnapActionStatus = kASEnterCircusWihoutTicket; +					_hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE; +				} +			} +			break; +		 +		case kHSPosters1: +		case kHSPosters2: +		case kHSPosters3: +		case kHSPosters4: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						gnapWalkTo(_hotspotsWalkPos[_sceneClickedHotspot].x, _hotspotsWalkPos[_sceneClickedHotspot].y, -1, -1, 1); +						if (_sceneClickedHotspot == 5 || _sceneClickedHotspot == 6) +							_gnapIdleFacing = 5; +						else if (_sceneClickedHotspot == 8) +							_gnapIdleFacing = 1; +						else +							_gnapIdleFacing = 7; +						playGnapIdle(0, 0); +						scene25_playAnims(8 - _sceneClickedHotspot + 1); +						break; +					case GRAB_CURSOR: +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapMoan2(0, 0); +						break; +					} +				} +			} +			break; +		 +		case kHSWalkArea1: +		case kHSWalkArea2: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; +		 +		default: +			if (_mouseClickState.left) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +		 +		} +	 +		scene25_updateAnimations(); +	 +		if (!_isLeavingScene) { +			updateBeaverIdleSequence(); +			updateGnapIdleSequence(); +			if (!_timers[4] && _s25_nextTicketVendorSequenceId == -1 && _gnapActionStatus == -1) { +				_timers[4] = getRandom(20) + 20; +				switch (getRandom(13)) { +				case 0: +					_s25_nextTicketVendorSequenceId = 0x54; +					break; +				case 1: +					_s25_nextTicketVendorSequenceId = 0x58; +					break; +				case 2: +					_s25_nextTicketVendorSequenceId = 0x55; +					break; +				case 3: +					_s25_nextTicketVendorSequenceId = 0x5A; +					break; +				case 4: +				case 5: +				case 6: +				case 7: +					_s25_nextTicketVendorSequenceId = 0x5B; +					break; +				case 8: +				case 9: +				case 10: +				case 11: +					_s25_nextTicketVendorSequenceId = 0x5C; +					break; +				case 12: +					_s25_nextTicketVendorSequenceId = 0x5D; +					break; +				default: +					_s25_nextTicketVendorSequenceId = 0x52; +					break; +				} +			} +			playSoundA(); +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene25_updateHotspots(); +		} +		 +		gameUpdateTick(); +		 +	} + +} + +void GnapEngine::scene25_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASTalkTicketVendor: +			_s25_nextTicketVendorSequenceId = (getRandom(2) == 1) ? 0x57 : 0x5F; +			_gnapActionStatus = -1; +			break; +		case kASEnterCircusWihoutTicket: +			_s25_nextTicketVendorSequenceId = 0x5E; +			_gameSys->setAnimation(0x5E, 39, 0); +			_gameSys->setAnimation(_s25_nextTicketVendorSequenceId, 39, 3); +			_gameSys->insertSequence(_s25_nextTicketVendorSequenceId, 39, _s25_currTicketVendorSequenceId, 39, 32, 0, 0, 0); +			_gameSys->insertSequence(0x60, 2, 0, 0, kSeqNone, 0, 0, 0); +			_s25_currTicketVendorSequenceId = _s25_nextTicketVendorSequenceId; +			_s25_nextTicketVendorSequenceId = -1; +			_hotspots[kHSWalkArea1].flags |= SF_WALKABLE; +			playGnapIdle(0, 0); +			gnapWalkTo(_hotspotsWalkPos[3].x, _hotspotsWalkPos[3].y, -1, 0x107BB, 1); +			_hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE; +			_gnapActionStatus = kASEnterCircusWihoutTicketDone; +			break; +		case kASEnterCircusWihoutTicketDone: +			_gnapActionStatus = -1; +			break; +		case kASShowTicketToVendor: +			setGrabCursorSprite(-1); +			invRemove(kItemTickets); +			setFlag(2); +			_gameSys->setAnimation(0x61, 40, 0); +			_gameSys->insertSequence(0x61, 40, 0, 0, kSeqNone, 0, 0, 0); +			_gnapActionStatus = kASShowTicketToVendorDone; +			break; +		case kASShowTicketToVendorDone: +			_s25_nextTicketVendorSequenceId = 0x53; +			break; +		case kASLeaveScene: +			_sceneDone = true; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2) { +		if (_s25_nextTicketVendorSequenceId == 0x53) { +			_gameSys->insertSequence(_s25_nextTicketVendorSequenceId, 39, _s25_currTicketVendorSequenceId, 39, kSeqSyncWait, 0, 0, 0); +			_s25_currTicketVendorSequenceId = _s25_nextTicketVendorSequenceId; +			_s25_nextTicketVendorSequenceId = -1; +			_gnapActionStatus = -1; +		} else if (_s25_nextTicketVendorSequenceId != -1) { +			_gameSys->setAnimation(_s25_nextTicketVendorSequenceId, 39, 3); +			_gameSys->insertSequence(_s25_nextTicketVendorSequenceId, 39, _s25_currTicketVendorSequenceId, 39, kSeqSyncWait, 0, 0, 0); +			_s25_currTicketVendorSequenceId = _s25_nextTicketVendorSequenceId; +			_s25_nextTicketVendorSequenceId = -1; +		} +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene26.cpp b/engines/gnap/scenes/scene26.cpp new file mode 100644 index 0000000000..644db6b3fd --- /dev/null +++ b/engines/gnap/scenes/scene26.cpp @@ -0,0 +1,256 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus					= 0, +	kHSExitOutsideCircusWorld	= 1, +	kHSExitOutsideClown			= 2, +	kHSExitArcade				= 3, +	kHSExitElephant				= 4, +	kHSExitBeerStand			= 5, +	kHSDevice					= 6, +	kHSWalkArea1				= 7, +	kHSWalkArea2				= 8 +}; + +enum { +	kASLeaveScene					= 0 +}; + +int GnapEngine::scene26_init() { +	return isFlag(23) ? 0x61 : 0x60; +} + +void GnapEngine::scene26_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitOutsideCircusWorld, 0, 590, 300, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 1, 10); +	setHotspot(kHSExitOutsideClown, 200, 265, 265, 350, SF_EXIT_U_CURSOR, 3, 8); +	setHotspot(kHSExitArcade, 0, 295, 150, 400, SF_EXIT_NW_CURSOR, 2, 8); +	setHotspot(kHSExitElephant, 270, 290, 485, 375, SF_EXIT_U_CURSOR, 5, 8); +	setHotspot(kHSExitBeerStand, 530, 290, 620, 350, SF_EXIT_NE_CURSOR, 5, 8); +	setHotspot(kHSWalkArea1, 0, 0, 800, 500); +	setHotspot(kHSWalkArea2, 281, 0, 800, 600); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 9; +} + +void GnapEngine::scene26_run() { +	 +	startSoundTimerB(7); +	playSound(0x1093B, 1); + +	_s26_currKidSequenceId = 0x5B; +	_s26_nextKidSequenceId = -1; +	_gameSys->setAnimation(0x5B, 160, 3); +	_gameSys->insertSequence(_s26_currKidSequenceId, 160, 0, 0, kSeqNone, 0, 0, 0); + +	_timers[5] = getRandom(20) + 50; +	_timers[4] = getRandom(20) + 50; +	_timers[6] = getRandom(50) + 100; + +	queueInsertDeviceIcon(); + +	_gameSys->insertSequence(0x58, 40, 0, 0, kSeqLoop, 0, 0, 0); +	_gameSys->insertSequence(0x5C, 40, 0, 0, kSeqLoop, 0, 0, 0); +	_gameSys->insertSequence(0x5D, 40, 0, 0, kSeqLoop, 0, 0, 0); +	_gameSys->insertSequence(0x5E, 40, 0, 0, kSeqLoop, 0, 0, 0); +	 +	if (_prevSceneNum == 25) { +		initGnapPos(-1, 8, 1); +		initBeaverPos(-2, 8, 0); +		endSceneInit(); +		gnapWalkTo(2, 8, -1, 0x107B9, 1); +		platypusWalkTo(1, 8, -1, 0x107C2, 1); +	} else { +		initGnapPos(2, 8, 1); +		initBeaverPos(3, 8, 0); +		endSceneInit(); +	} + +	while (!_sceneDone) { + +		updateMouseCursor(); +		updateCursorByHotspot(); + +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); + +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene26_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemJoint) { +					gnapUseJointOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan1(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSExitOutsideCircusWorld: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				_newSceneNum = 25; +				gnapWalkTo(-1, _hotspotsWalkPos[kHSExitOutsideCircusWorld].y, 0, 0x107AE, 1); +				_gnapActionStatus = kASLeaveScene; +			} +			break; + +		case kHSExitOutsideClown: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				_newSceneNum = 27; +				gnapWalkTo(-1, _hotspotsWalkPos[kHSExitOutsideClown].y, 0, 0x107BC, 1); +				_gnapActionStatus = kASLeaveScene; +			} +			break; + +		case kHSExitArcade: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				_newSceneNum = 29; +				gnapWalkTo(-1, _hotspotsWalkPos[kHSExitArcade].y, 0, 0x107BC, 1); +				_gnapActionStatus = kASLeaveScene; +			} +			break; + +		case kHSExitElephant: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				_newSceneNum = 30; +				gnapWalkTo(-1, _hotspotsWalkPos[4].y, 0, 0x107BC, 1); +				_gnapActionStatus = kASLeaveScene; +			} +			break; + +		case kHSExitBeerStand: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				_newSceneNum = 31; +				gnapWalkTo(-1, _hotspotsWalkPos[kHSExitBeerStand].y, 0, 0x107BB, 1); +				_gnapActionStatus = kASLeaveScene; +			} +			break; + +		case kHSWalkArea1: +		case kHSWalkArea2: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; +			 +		default: +			if (_mouseClickState.left) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +			 +		} + +		scene26_updateAnimations(); + +		if (!isSoundPlaying(0x1093B)) +			playSound(0x1093B, 1); + +		if (!_isLeavingScene) { +			updateBeaverIdleSequence(); +			updateGnapIdleSequence(); +			if (!_timers[5] && _s26_nextKidSequenceId == -1) { +				_timers[5] = getRandom(20) + 50; +				if (getRandom(5) != 0) +					_s26_nextKidSequenceId = 0x5B; +				else +					_s26_nextKidSequenceId = 0x5A; +			} +			if (!_timers[4]) { +				_timers[4] = getRandom(20) + 130; +				_gameSys->insertSequence(0x59, 40, 0, 0, kSeqNone, 0, 0, 0); +			} +			if (!_timers[6]) { +				_timers[6] = getRandom(50) + 100; +				_gameSys->insertSequence(0x5F, 40, 0, 0, kSeqNone, 0, 0, 0); +			} +			playSoundB(); +		} + +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene26_updateHotspots(); +		} +		 +		gameUpdateTick(); + +	} +	 +} + +void GnapEngine::scene26_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		if (_gnapActionStatus == kASLeaveScene) +			_sceneDone = true; +		_gnapActionStatus = -1; +	} + +	if (_gameSys->getAnimationStatus(3) == 2 && _s26_nextKidSequenceId != -1) { +		_gameSys->insertSequence(_s26_nextKidSequenceId, 160, _s26_currKidSequenceId, 160, kSeqSyncWait, 0, 0, 0); +		_gameSys->setAnimation(_s26_nextKidSequenceId, 160, 3); +		_s26_currKidSequenceId = _s26_nextKidSequenceId; +		_s26_nextKidSequenceId = -1; +	} +	 +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene27.cpp b/engines/gnap/scenes/scene27.cpp new file mode 100644 index 0000000000..000a94203c --- /dev/null +++ b/engines/gnap/scenes/scene27.cpp @@ -0,0 +1,423 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus			= 0, +	kHSJanitor		= 1, +	kHSDevice			= 2, +	kHSBucket			= 3, +	kHSExitCircus		= 4, +	kHSExitArcade		= 5, +	kHSExitBeerStand	= 6, +	kHSExitClown		= 7, +	kHSWalkArea1		= 8 +}; + +enum { +	kASTalkJanitor				= 0, +	kASGrabBucket				= 1, +	kASGrabBucketDone			= 2, +	kASShowPictureToJanitor		= 3, +	kASTryEnterClownTent		= 4, +	kASTryEnterClownTentDone	= 5, +	kASEnterClownTent			= 6, +	kASLeaveScene				= 7 +}; + +int GnapEngine::scene27_init() { +	return 0xD5; +} + +void GnapEngine::scene27_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSJanitor, 488, 204, 664, 450, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 8, 8); +	setHotspot(kHSBucket, 129, 406, 186, 453, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 6); +	setHotspot(kHSExitCircus, 200, 585, 700, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9); +	setHotspot(kHSExitArcade, 0, 0, 15, 600, SF_EXIT_L_CURSOR, 0, 6); +	setHotspot(kHSExitBeerStand, 785, 0, 800, 600, SF_EXIT_R_CURSOR, 11, 7); +	setHotspot(kHSExitClown, 340, 240, 460, 420, SF_EXIT_U_CURSOR, 6, 8); +	setHotspot(kHSWalkArea1, 0, 0, 800, 507); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	if (isFlag(13)) +		_hotspots[kHSBucket].flags = SF_DISABLED; +	_hotspotsCount = 9; +} + +void GnapEngine::scene27_run() { +	 +	playSound(0x1093B, 1); +	startSoundTimerB(4); +	_timers[7] = getRandom(100) + 300; +	queueInsertDeviceIcon(); + +	if (!isFlag(13)) +		_gameSys->insertSequence(0xD3, 39, 0, 0, kSeqNone, 0, 0, 0); + +	if (_debugLevel == 4) +		startIdleTimer(6); + +	_gameSys->insertSequence(0xCB, 39, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s27_currJanitorSequenceId = 0xCB; +	_s27_nextJanitorSequenceId = -1; +	 +	_gameSys->setAnimation(0xCB, 39, 3); + +	_timers[5] = getRandom(20) + 60; + +	switch (_prevSceneNum) { +	case 26: +		initGnapPos(7, 12, 1); +		initBeaverPos(6, 12, 0); +		endSceneInit(); +		gnapWalkTo(7, 8, -1, 0x107B9, 1); +		platypusWalkTo(6, 8, -1, 0x107C2, 1); +		break; +	case 29: +		initGnapPos(-1, 8, 1); +		initBeaverPos(-1, 9, 0); +		endSceneInit(); +		gnapWalkTo(3, 8, -1, 0x107B9, 1); +		platypusWalkTo(3, 9, -1, 0x107C2, 1); +		break; +	case 31: +		initGnapPos(12, 8, 3); +		initBeaverPos(12, 9, 4); +		endSceneInit(); +		gnapWalkTo(8, 8, -1, 0x107BA, 1); +		platypusWalkTo(8, 9, -1, 0x107C2, 1); +		break; +	default: +		initGnapPos(6, 8, 1); +		initBeaverPos(5, 9, 0); +		endSceneInit(); +		break; +	} + +	while (!_sceneDone) { + +		updateMouseCursor(); +		updateCursorByHotspot(); +		_sceneClickedHotspot = -1; +		if (_gnapActionStatus < 0) +			_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); + +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene27_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemJoint) { +					gnapUseJointOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan1(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSJanitor: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemPicture) { +					_gnapIdleFacing = 5; +					if (gnapWalkTo(_hotspotsWalkPos[kHSJanitor].x, _hotspotsWalkPos[kHSJanitor].y, 0, 0x107BC, 1)) +						_gnapActionStatus = kASShowPictureToJanitor; +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSJanitor].x, _hotspotsWalkPos[kHSJanitor].y, 7, 3); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(6, 3); +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 5; +						gnapWalkTo(_hotspotsWalkPos[kHSJanitor].x, _hotspotsWalkPos[kHSJanitor].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = kASTalkJanitor; +						break; +					case GRAB_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSBucket: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowItem(_grabCursorSpriteIndex, 3, 3); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(3, 3); +						break; +					case GRAB_CURSOR: +						_gnapIdleFacing = 5; +						gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, _hotspotsWalkPos[kHSBucket].x, _hotspotsWalkPos[kHSBucket].y) | 0x10000, 1); +						_gnapActionStatus = kASGrabBucket; +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSExitCircus: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				_newSceneNum = 26; +				gnapWalkTo(-1, _hotspotsWalkPos[kHSExitCircus].y, 0, 0x107AE, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[kHSExitCircus].x + 1, _hotspotsWalkPos[kHSExitCircus].y, -1, 0x107C7, 1); +			} +			break; + +		case kHSExitArcade: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				_newSceneNum = 29; +				gnapWalkTo(-1, _hotspotsWalkPos[kHSExitArcade].y, 0, 0x107AF, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[kHSExitArcade].x, _hotspotsWalkPos[kHSExitArcade].y + 1, -1, 0x107CF, 1); +			} +			break; + +		case kHSExitBeerStand: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				_newSceneNum = 31; +				gnapWalkTo(-1, _hotspotsWalkPos[kHSExitBeerStand].y, 0, 0x107AB, 1); +				_gnapActionStatus = kASLeaveScene; +				platypusWalkTo(_hotspotsWalkPos[kHSExitBeerStand].x, _hotspotsWalkPos[kHSExitBeerStand].y + 1, -1, 0x107CD, 1); +			} +			break; + +		case kHSExitClown: +			if (_gnapActionStatus < 0) { +				if (isFlag(0)) { +					_isLeavingScene = true; +					_newSceneNum = 28; +					gnapWalkTo(_hotspotsWalkPos[kHSExitClown].x, _hotspotsWalkPos[kHSExitClown].y, 0, 0x107AD, 1); +					_gnapActionStatus = kASLeaveScene; +					platypusWalkTo(_hotspotsWalkPos[kHSExitClown].x + 1, _hotspotsWalkPos[kHSExitClown].y, -1, 0x107C4, 1); +				} else { +					_hotspots[kHSWalkArea1].flags |= SF_WALKABLE; +					gnapWalkTo(_hotspotsWalkPos[kHSExitClown].x, 7, 0, 0x107BC, 1); +					_hotspots[kHSWalkArea1].flags &= SF_WALKABLE; +					_gnapActionStatus = kASTryEnterClownTent; +				} +			} +			break; + +		case kHSWalkArea1: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; +			 +		default: +			if (_mouseClickState.left && _gnapActionStatus < 0) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +		 +		} +	 +		scene27_updateAnimations(); + +		if (!isSoundPlaying(0x1093B)) +			playSound(0x1093B, 1); + +		if (!_isLeavingScene) { +			updateBeaverIdleSequence(); +			if (_gnapActionStatus < 0) +				updateGnapIdleSequence(); +			if (_debugLevel == 4) +				updateIdleTimer(); +			if (!_timers[5]) { +				_timers[5] = getRandom(20) + 60; +				if (_gnapActionStatus < 0) { +					if (getRandom(3) != 0) +						_s27_nextJanitorSequenceId = 0xCB; +					else +						_s27_nextJanitorSequenceId = 0xCF; +				} +			} +			if (!_timers[7]) { +				_timers[7] = getRandom(100) + 300; +				if (_gnapActionStatus < 0) +					_gameSys->insertSequence(0xD4, 120, 0, 0, kSeqNone, 0, 0, 0); +			} +			playSoundB(); +		} + +		checkGameKeys(); + +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene27_updateHotspots(); +		} +		 +		gameUpdateTick(); + +	} +	 +} + +void GnapEngine::scene27_updateAnimations() { +	 +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case kASTalkJanitor: +			switch (getRandom(3)) { +			case 0: +				_s27_nextJanitorSequenceId = 0xCC; +				break; +			case 1: +				_s27_nextJanitorSequenceId = 0xCD; +				break; +			case 2: +				_s27_nextJanitorSequenceId = 0xCE; +				break; +			} +			break; +		case kASGrabBucket: +			playGnapPullOutDevice(0, 0); +			playGnapUseDevice(0, 0); +			_hotspots[kHSBucket].flags = SF_DISABLED; +			invAdd(kItemEmptyBucket); +			setFlag(13); +			_gameSys->setAnimation(0xD2, 39, 0); +			_gameSys->insertSequence(0xD2, 39, 211, 39, kSeqSyncWait, 0, 0, 0); +			_gnapActionStatus = kASGrabBucketDone; +			break; +		case kASGrabBucketDone: +			setGrabCursorSprite(kItemEmptyBucket); +			_gnapActionStatus = -1; +			break; +		case kASShowPictureToJanitor: +			_s27_nextJanitorSequenceId = 0xD0; +			break; +		case kASTryEnterClownTent: +			_s27_nextJanitorSequenceId = 0xD1; +			_gameSys->insertSequence(0xD1, 39, _s27_currJanitorSequenceId, 39, 32, 0, 0, 0); +			_gameSys->setAnimation(_s27_nextJanitorSequenceId, 39, 3); +			_gameSys->setAnimation(_s27_nextJanitorSequenceId, 39, 0); +			_s27_currJanitorSequenceId = _s27_nextJanitorSequenceId; +			_s27_nextJanitorSequenceId = -1; +			_gnapActionStatus = kASTryEnterClownTentDone; +			break; +		case kASTryEnterClownTentDone: +			_hotspots[kHSWalkArea1].flags |= SF_WALKABLE; +			gnapWalkTo(_hotspotsWalkPos[7].x, 9, -1, 0x107BC, 1); +			_hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE; +			_gnapActionStatus = -1; +			break; +		case kASEnterClownTent: +			gnapWalkTo(_gnapX, _gnapY, 0, 0x107B2, 1); +			_gnapActionStatus = kASLeaveScene; +			break; +		case kASLeaveScene: +			_sceneDone = true; +			break; +		} +	} + +	if (_gameSys->getAnimationStatus(3) == 2) { +		switch (_s27_nextJanitorSequenceId) { +		case -1: +			_s27_nextJanitorSequenceId = 0xCB; +			_gameSys->insertSequence(0xCB, 39, _s27_currJanitorSequenceId, 39, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s27_nextJanitorSequenceId, 39, 3); +			_s27_currJanitorSequenceId = _s27_nextJanitorSequenceId; +			_s27_nextJanitorSequenceId = -1; +			break; +		case 0xCC: +		case 0xCD: +		case 0xCE: +			_gnapActionStatus = -1; +			_gameSys->insertSequence(_s27_nextJanitorSequenceId, 39, _s27_currJanitorSequenceId, 39, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s27_nextJanitorSequenceId, 39, 3); +			_gameSys->setAnimation(_s27_nextJanitorSequenceId, 39, 0); +			_s27_currJanitorSequenceId = _s27_nextJanitorSequenceId; +			_s27_nextJanitorSequenceId = -1; +			break; +		case 0xD0: +			// Show picture to janitor +			playGnapPullOutDevice(0, 0); +			playGnapUseDevice(0, 0); +			_gameSys->insertSequence(_s27_nextJanitorSequenceId, 39, _s27_currJanitorSequenceId, 39, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s27_nextJanitorSequenceId, 39, 0); +			_gnapActionStatus = kASEnterClownTent; +			_s27_currJanitorSequenceId = _s27_nextJanitorSequenceId; +			_s27_nextJanitorSequenceId = -1; +			setFlag(0); +			setGrabCursorSprite(-1); +			invRemove(kItemPicture); +			_newSceneNum = 28; +			break; +		default: +			_gameSys->insertSequence(_s27_nextJanitorSequenceId, 39, _s27_currJanitorSequenceId, 39, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s27_nextJanitorSequenceId, 39, 3); +			_s27_currJanitorSequenceId = _s27_nextJanitorSequenceId; +			_s27_nextJanitorSequenceId = -1; +			break; +		} +	} +   +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene28.cpp b/engines/gnap/scenes/scene28.cpp new file mode 100644 index 0000000000..23c3e52974 --- /dev/null +++ b/engines/gnap/scenes/scene28.cpp @@ -0,0 +1,435 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus			= 0, +	kHSHorn				= 1, +	kHSClown			= 2, +	kHSExitOutsideClown	= 3, +	kHSUnknown			= 4, +	kHSDevice			= 5, +	kHSWalkArea1		= 6, +	kHSWalkArea2		= 7 +}; + +int GnapEngine::scene28_init() { +	return 0x125; +} + +void GnapEngine::scene28_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSHorn, 148, 352, 215, 383, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 1, 7); +	setHotspot(kHSClown, 130, 250, 285, 413, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 5); +	setHotspot(kHSExitOutsideClown, 660, 190, 799, 400, SF_EXIT_R_CURSOR, 9, 6); +	setHotspot(kHSUnknown, 582, 421, 643, 478, SF_WALKABLE | SF_DISABLED, 9, 7); +	setHotspot(kHSWalkArea1, 0, 0, 799, 523); +	setHotspot(kHSWalkArea2, 0, 0, 0, 0, 7, SF_DISABLED); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	if (invHas(kItemHorn)) +		_hotspots[kHSHorn].flags = SF_DISABLED; +	if (isFlag(22)) +		_hotspots[kHSUnknown].flags = SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR; +	_hotspotsCount = 8; +} + +void GnapEngine::scene28_run() { + +	playSound(0x1093C, 1); +	_s28_dword_47EA60 = -1; +	queueInsertDeviceIcon(); +	_gameSys->insertSequence(0x124, 255, 0, 0, kSeqNone, 0, 0, 0); + +	if (isFlag(22)) +		_gameSys->insertSequence(0x112, 99, 0, 0, kSeqNone, 0, 0, 0); + +	if (isFlag(1)) { +		if (isFlag(21)) { +			_gameSys->setAnimation(0x11C, 39, 3); +			_gameSys->insertSequence(0x11C, 39, 0, 0, kSeqNone, 0, 0, 0); +			if (!invHas(kItemHorn)) +				_gameSys->insertSequence(0x118, 59, 0, 0, kSeqNone, 0, 0, 0); +			_s28_dword_47EA5C = 0x11C; +		} else { +			_s28_dword_47EA5C = 0x11B; +			_gameSys->setAnimation(0x11B, 39, 3); +			_gameSys->insertSequence(_s28_dword_47EA5C, 39, 0, 0, kSeqNone, 0, 0, 0); +			_timers[4] = getRandom(20) + 80; +		} +		initGnapPos(8, 8, 3); +		initBeaverPos(9, 8, 4); +		endSceneInit(); +	} else { +		_gameSys->insertSequence(0x11B, 39, 0, 0, kSeqNone, 0, 0, 0); +		initGnapPos(8, 8, 3); +		initBeaverPos(9, 8, 4); +		endSceneInit(); +		playSequences(0xF7, 0x121, 0x122, 0x123); +		_s28_dword_47EA5C = 0x115; +		setFlag(1); +		_gameSys->setAnimation(0x115, 39, 3); +		_gameSys->insertSequence(_s28_dword_47EA5C, 39, 283, 39, kSeqSyncWait, 0, 0, 0); +		_s28_dword_47EA60 = -1; +		_timers[4] = getRandom(20) + 80; +		_gnapActionStatus = 9; +		while (_gameSys->getAnimationStatus(3) != 2) { +			gameUpdateTick(); +			updateMouseCursor(); +		} +		_gnapActionStatus = -1; +	} + +	while (!_sceneDone) { + +		updateMouseCursor(); +		updateCursorByHotspot(); + +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); + +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene28_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemJoint) { +					gnapUseJointOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan1(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSHorn: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(2, 8, 3, 4); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(2, 4); +						break; +					case GRAB_CURSOR: +						if (isFlag(21)) { +							if (!invHas(kItemHorn)) { +								gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, _hotspotsWalkPos[kHSHorn].x, _hotspotsWalkPos[kHSHorn].y) | 0x10000, 1); +								_gnapActionStatus = 4; +							} +						} else { +							_gnapIdleFacing = 5; +							gnapWalkTo(2, 8, 0, 0x107BB, 1); +							_hotspots[kHSWalkArea1].flags |= SF_WALKABLE; +							gnapWalkTo(_hotspotsWalkPos[kHSHorn].x, _hotspotsWalkPos[kHSHorn].y, 0, 0x107BB, 1); +							_hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE; +							_gnapActionStatus = 2; +						} +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSClown: +			if (_gnapActionStatus < 0) { +				if (isFlag(21)) { +					if (_verbCursor == LOOK_CURSOR) +						playGnapScratchingHead(5, 2); +					else +						playGnapImpossible(0, 0); +				} else if (_grabCursorSpriteIndex == kItemBucketWithBeer) { +					_gnapIdleFacing = 5; +					gnapWalkTo(_hotspotsWalkPos[kHSClown].x, _hotspotsWalkPos[kHSClown].y, 0, 0x107BC, 1); +					playGnapPullOutDevice(0, 0); +					playGnapUseDevice(0, 0); +					_gnapActionStatus = 0; +				} else if (_grabCursorSpriteIndex == kItemBucketWithPill) { +					_gnapIdleFacing = 5; +					gnapWalkTo(_hotspotsWalkPos[kHSClown].x, _hotspotsWalkPos[kHSClown].y, 0, 0x107BC, 1); +					playGnapPullOutDevice(0, 0); +					playGnapUseDevice(0, 0); +					_gnapActionStatus = 1; +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSClown].x, _hotspotsWalkPos[kHSClown].y, 2, 4); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(5, 2); +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 5; +						gnapWalkTo(5, 8, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = 8; +						break; +					case GRAB_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSExitOutsideClown: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				_newSceneNum = 27; +				_hotspots[kHSWalkArea1].flags |= SF_WALKABLE; +				gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideClown].x, _hotspotsWalkPos[kHSExitOutsideClown].y, 0, 0x107BF, 1); +				_gnapActionStatus = 10; +				_hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE; +				platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideClown].x - 1, _hotspotsWalkPos[kHSExitOutsideClown].y, -1, 0x107C2, 1); +			} +			break; + +		case kHSUnknown: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowItem(_grabCursorSpriteIndex, 8, 6); +				} else if (isFlag(21)) { +					playGnapImpossible(8, 6); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(8, 6); +						break; +					case GRAB_CURSOR: +						gnapWalkTo(_gnapX, _gnapY, 0, getGnapSequenceId(gskIdle, _hotspotsWalkPos[kHSUnknown].x, _hotspotsWalkPos[kHSUnknown].y) | 0x10000, 1); +						_gnapActionStatus = 3; +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSWalkArea1: +		case kHSWalkArea2: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; +			 +		default: +			if (_mouseClickState.left && _gnapActionStatus < 0) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +			 +		} + +		scene28_updateAnimations(); + +		if (!isSoundPlaying(0x1093C)) +			playSound(0x1093C, 1); + +		if (!_isLeavingScene) { +			updateBeaverIdleSequence(); +			updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = getRandom(20) + 80; +				if (_gnapActionStatus < 0 && !isFlag(21)) +					_s28_dword_47EA60 = 0x114; +			} +		} + +		checkGameKeys(); + +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene28_updateHotspots(); +		} +		 +		gameUpdateTick(); + +	} +	 +} + +void GnapEngine::scene28_updateAnimations() { +	 +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case 0: +			setFlag(22); +			_s28_dword_47EA60 = 275; +			invRemove(kItemBucketWithBeer); +			scene28_updateHotspots(); +			break; +		case 1: +			_s28_dword_47EA60 = 0x116; +			invRemove(kItemBucketWithPill); +			setFlag(22); +			setFlag(21); +			scene28_updateHotspots(); +			break; +		case 2: +			_s28_dword_47EA60 = 0x119; +			break; +		case 3: +			playGnapPullOutDevice(0, 0); +			playGnapUseDevice(0, 0); +			_gameSys->setAnimation(0x111, 99, 0); +			_gameSys->insertSequence(0x111, 99, 274, 99, kSeqSyncWait, 0, 0, 0); +			_gnapActionStatus = 6; +			break; +		case 4: +			playGnapPullOutDevice(0, 0); +			playGnapUseDevice(0, 0); +			_gameSys->setAnimation(0x117, 59, 0); +			_gameSys->insertSequence(0x117, 59, 280, 59, kSeqSyncWait, 0, 0, 0); +			_gnapActionStatus = 5; +			break; +		case 5: +			hideCursor(); +			setGrabCursorSprite(-1); +			addFullScreenSprite(0xF6, 255); +			_gameSys->setAnimation(0x120, 256, 0); +			_gameSys->insertSequence(0x120, 256, 0, 0, kSeqNone, 0, 0, 0); +			while (_gameSys->getAnimationStatus(0) != 2) +				gameUpdateTick(); +			removeFullScreenSprite(); +			showCursor(); +			setGrabCursorSprite(kItemHorn); +			invAdd(kItemHorn); +			scene28_updateHotspots(); +			_gnapActionStatus = -1; +			break; +		case 6: +			setGrabCursorSprite(kItemEmptyBucket); +			clearFlag(22);; +			scene28_updateHotspots(); +			invAdd(kItemEmptyBucket); +			_gnapActionStatus = -1; +			break; +		case 7: +			_gameSys->insertSequence(0x107B5, _gnapId, 281, 39, kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +			_gnapSequenceId = 0x7B5; +			_gnapSequenceDatNum = 1; +			_gameSys->insertSequence(0x11B, 39, 0, 0, kSeqNone, 0, 0, 0); +			_s28_dword_47EA5C = 0x11B; +			_s28_dword_47EA60 = -1; +			_gnapActionStatus = -1; +			gnapWalkTo(2, 8, -1, 0x107BB, 1); +			break; +		case 8: +			_s28_dword_474938 = (_s28_dword_474938 + 1) % 2; +			if (_s28_dword_474938 == 0) +				_s28_dword_47EA60 = 0x11D; +			else if (_s28_dword_474938 == 1) +				_s28_dword_47EA60 = 0x11E; +			else if (_s28_dword_474938 == 2) +				_s28_dword_47EA60 = 0x11F; // NOTE CHECKME Never set, bug in the original? +			break; +		case 9: +			_gnapActionStatus = -1; +			break; +		case 10: +			_sceneDone = true; +			break; +		} +	} + +	if (_gameSys->getAnimationStatus(3) == 2) { +		switch (_s28_dword_47EA60) { +		case 0x113: +			setGrabCursorSprite(-1); +			_gameSys->setAnimation(_s28_dword_47EA60, 39, 0); +			_gameSys->insertSequence(0x112, 99, 0, 0, kSeqNone, getSequenceTotalDuration(_s28_dword_47EA60), 0, 0); +			_gameSys->insertSequence(_s28_dword_47EA60, 39, _s28_dword_47EA5C, 39, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x11B, 39, _s28_dword_47EA60, 39, kSeqSyncWait, 0, 0, 0); +			_s28_dword_47EA5C = 0x11B; +			_s28_dword_47EA60 = -1; +			_gnapActionStatus = 9; +			break; +		case 0x116: +			setGrabCursorSprite(-1); +			_gameSys->setAnimation(_s28_dword_47EA60, 39, 0); +			_gameSys->insertSequence(0x112, 99, 0, 0, kSeqNone, getSequenceTotalDuration(_s28_dword_47EA60), 0, 0); +			_gameSys->insertSequence(_s28_dword_47EA60, 39, _s28_dword_47EA5C, 39, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x11C, 39, _s28_dword_47EA60, 39, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0x118, 59, 0, 0, kSeqNone, getSequenceTotalDuration(_s28_dword_47EA60), 0, 0); +			_s28_dword_47EA5C = _s28_dword_47EA60; +			_s28_dword_47EA60 = -1; +			_gnapActionStatus = 9; +			break; +		case 0x11D: +		case 0x11E: +		case 0x11F: +			_gnapActionStatus = -1; +			break; +		case 0x119: +			_gameSys->insertSequence(_s28_dword_47EA60, 39, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s28_dword_47EA60, 39, 0); +			_gameSys->removeSequence(_s28_dword_47EA5C, 39, 1); +			_gnapActionStatus = 7; +			_gnapSequenceId = _s28_dword_47EA60; +			_gnapSequenceDatNum = 0; +			_s28_dword_47EA60 = -1; +			break; +		} +		if (_s28_dword_47EA60 != -1) { +			_gameSys->insertSequence(_s28_dword_47EA60, 39, _s28_dword_47EA5C, 39, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s28_dword_47EA60, 39, 3); +			_s28_dword_47EA5C = _s28_dword_47EA60; +			_s28_dword_47EA60 = -1; +		} +	} +	 +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene29.cpp b/engines/gnap/scenes/scene29.cpp new file mode 100644 index 0000000000..3a78107db5 --- /dev/null +++ b/engines/gnap/scenes/scene29.cpp @@ -0,0 +1,352 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus			= 0, +	kHSMonkey			= 1, +	kHSDevice			= 2, +	kHSExitCircus		= 3, +	kHSExitOutsideClown	= 4, +	kHSAracde			= 5, +	kHSWalkArea1		= 6 +}; + +int GnapEngine::scene29_init() { +	return 0xF6; +} + +void GnapEngine::scene29_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSMonkey, 410, 374, 518, 516, SF_WALKABLE | SF_DISABLED, 3, 7); +	setHotspot(kHSExitCircus, 150, 585, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9); +	setHotspot(kHSExitOutsideClown, 785, 0, 800, 600, SF_EXIT_R_CURSOR | SF_WALKABLE, 11, 9); +	setHotspot(kHSAracde, 88, 293, 155, 384, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 8); +	setHotspot(kHSWalkArea1, 0, 0, 800, 478); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	if (invHas(kItemHorn)) +		_hotspots[kHSMonkey].flags = SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR; +	_hotspotsCount = 7; +} + +void GnapEngine::scene29_run() { +	 +	playSound(0x1093B, 1); +	startSoundTimerB(6); +	queueInsertDeviceIcon(); + +	if (invHas(kItemHorn)) { +		_s29_dword_47EA74 = 0xE8; +		_s29_dword_47EA78 = -1; +		_gameSys->setAnimation(0xE8, 159, 4); +		_gameSys->insertSequence(_s29_dword_47EA74, 159, 0, 0, kSeqNone, 0, 0, 0); +		_gameSys->insertSequence(0xED, 39, 0, 0, kSeqNone, 0, 0, 0); +		_s29_dword_47EA7C = 0xED; +		_s29_dword_47EA80 = -1; +		_gameSys->setAnimation(0xED, 39, 3); +		_timers[4] = getRandom(20) + 60; +	} else { +		_gameSys->insertSequence(0xF4, 19, 0, 0, kSeqNone, 0, 0, 0); +		_gameSys->setAnimation(0, 0, 4); +		_gameSys->insertSequence(0xED, 39, 0, 0, kSeqNone, 0, 0, 0); +		_gameSys->setAnimation(0, 0, 3); +	} +	 +	_gameSys->insertSequence(0xF3, 39, 0, 0, kSeqLoop, 0, 0, 0); +	_gameSys->insertSequence(0xF5, 38, 0, 0, kSeqLoop, 0, 0, 0); + +	if (_prevSceneNum == 27) { +		initGnapPos(12, 7, 1); +		initBeaverPos(12, 8, 0); +		endSceneInit(); +		gnapWalkTo(8, 7, -1, 0x107B9, 1); +		platypusWalkTo(8, 8, -1, 0x107C2, 1); +	} else { +		initGnapPos(-1, 7, 1); +		initBeaverPos(-2, 7, 0); +		endSceneInit(); +		gnapWalkTo(2, 7, -1, 0x107B9, 1); +		platypusWalkTo(1, 7, -1, 0x107C2, 1); +	} + +	while (!_sceneDone) { + +		updateMouseCursor(); +		updateCursorByHotspot(); +		 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene29_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemJoint) { +					gnapUseJointOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan1(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSMonkey: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemBanana) { +					_gnapIdleFacing = 1; +					gnapWalkTo(_hotspotsWalkPos[kHSMonkey].x, _hotspotsWalkPos[kHSMonkey].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1); +					_gnapActionStatus = 0; +					_newSceneNum = 51; +					_isLeavingScene = 1; +					setGrabCursorSprite(-1); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSMonkey].x, _hotspotsWalkPos[kHSMonkey].y, 5, 6); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(5, 6); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_hotspotsWalkPos[kHSMonkey].x, _hotspotsWalkPos[kHSMonkey].y); +						break; +					case GRAB_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSExitCircus: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				_newSceneNum = 26; +				gnapWalkTo(_hotspotsWalkPos[kHSExitCircus].x, _hotspotsWalkPos[kHSExitCircus].y, 0, 0x107AE, 1); +				_gnapActionStatus = 2; +				platypusWalkTo(_hotspotsWalkPos[kHSExitCircus].x + 1, _hotspotsWalkPos[kHSExitCircus].y, -1, -1, 1); +			} +			break; + +		case kHSExitOutsideClown: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				_newSceneNum = 27; +				gnapWalkTo(_hotspotsWalkPos[kHSExitOutsideClown].x, _hotspotsWalkPos[kHSExitOutsideClown].y, 0, 0x107AB, 1); +				_gnapActionStatus = 2; +				platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideClown].x, _hotspotsWalkPos[kHSExitOutsideClown].y - 1, -1, 0x107CD, 1); +			} +			break; + +		case kHSAracde: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemDiceQuarterHole) { +					setGrabCursorSprite(-1); +					_isLeavingScene = 1; +					_newSceneNum = 52; +					gnapWalkTo(_hotspotsWalkPos[kHSAracde].x, _hotspotsWalkPos[kHSAracde].y, 0, -1, 1); +					playGnapIdle(_hotspotsWalkPos[kHSAracde].x, _hotspotsWalkPos[kHSAracde].y); +					_gnapActionStatus = 2; +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSAracde].x, _hotspotsWalkPos[kHSAracde].y, 2, 3); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan2(0, 0); +						break; +					case GRAB_CURSOR: +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSWalkArea1: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; +		 +		default: +			if (_mouseClickState.left) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +		} +	 +		scene29_updateAnimations(); + +		if (!isSoundPlaying(0x1093B)) +			playSound(0x1093B, 1); + +		if (!_isLeavingScene) { +			if (_gnapActionStatus < 0) { +				updateGnapIdleSequence(); +				updateBeaverIdleSequence(); +			} +			if (!_timers[4]) { +				if (invHas(kItemHorn)) { +					_timers[4] = getRandom(20) + 60; +					if (_gnapActionStatus < 0) { +						switch (getRandom(5)) { +						case 0: +							_s29_dword_47EA80 = 0xED; +							break; +						case 1: +							_s29_dword_47EA80 = 0xEE; +							break; +						case 2: +							_s29_dword_47EA80 = 0xEF; +							break; +						case 3: +							_s29_dword_47EA80 = 0xF0; +							break; +						case 4: +							_s29_dword_47EA80 = 0xF1; +							break; +						} +					} +				} +			} +			playSoundB(); +		} +	 +		checkGameKeys(); + +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene29_updateHotspots(); +		} +		 +		gameUpdateTick(); +		 +	}		 + +} + +void GnapEngine::scene29_updateAnimations() { +	 +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case 0: +			_s29_dword_47EA78 = 0xE5; +			break; +		case 1: +		case 2: +			_sceneDone = true; +			break; +		} +	} + +	if (_gameSys->getAnimationStatus(3) == 2 && _s29_dword_47EA80 != -1) { +		_gameSys->insertSequence(_s29_dword_47EA80, 39, _s29_dword_47EA7C, 39, kSeqSyncWait, 0, 0, 0); +		_gameSys->setAnimation(_s29_dword_47EA80, 39, 3); +		_s29_dword_47EA7C = _s29_dword_47EA80; +		_s29_dword_47EA80 = -1; +	} + +	if (_gameSys->getAnimationStatus(4) == 2) { +		if (_s29_dword_47EA78 == 0xE5) { +			_gameSys->insertSequence(0xF2, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0xF2; +			_gameSys->setAnimation(0xE6, 159, 0); +			_gameSys->setAnimation(0, 159, 4); +			_gameSys->insertSequence(_s29_dword_47EA78, 159, _s29_dword_47EA74, 159, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0xE6, 159, _s29_dword_47EA78, 159, kSeqSyncWait, 0, 0, 0); +			_gnapActionStatus = 1; +			_s29_dword_47EA74 = 0xE6; +			_s29_dword_47EA78 = -1; +			_timers[5] = 30; +			while (_timers[5]) +				gameUpdateTick(); +			platypusWalkTo(0, 8, 1, 0x107CF, 1); +			while (_gameSys->getAnimationStatus(1) != 2) +				gameUpdateTick(); +		} else if (_s29_dword_47EA78 == -1) { +			switch (getRandom(6)) { +			case 0: +				_s29_dword_47EA78 = 0xE8; +				break; +			case 1: +				_s29_dword_47EA78 = 0xE9; +				break; +			case 2: +				_s29_dword_47EA78 = 0xEA; +				break; +			case 3: +				_s29_dword_47EA78 = 0xEB; +				break; +			case 4: +				_s29_dword_47EA78 = 0xEC; +				break; +			case 5: +				_s29_dword_47EA78 = 0xE7; +				break; +			} +			_gameSys->insertSequence(_s29_dword_47EA78, 159, _s29_dword_47EA74, 159, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s29_dword_47EA78, 159, 4); +			_s29_dword_47EA74 = _s29_dword_47EA78; +			_s29_dword_47EA78 = -1; +		} else { +			_gameSys->insertSequence(_s29_dword_47EA78, 159, _s29_dword_47EA74, 159, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s29_dword_47EA78, 159, 4); +			_s29_dword_47EA74 = _s29_dword_47EA78; +			_s29_dword_47EA78 = -1; +		} +	} +	 +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene30.cpp b/engines/gnap/scenes/scene30.cpp new file mode 100644 index 0000000000..341caee618 --- /dev/null +++ b/engines/gnap/scenes/scene30.cpp @@ -0,0 +1,281 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSPillMachine	= 1, +	kHSDevice		= 2, +	kHSExitCircus	= 3, +	kHSWalkArea1	= 4 +}; + +int GnapEngine::scene30_init() { +	return isFlag(23) ? 0x10B : 0x10A; +} + +void GnapEngine::scene30_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSPillMachine, 598, 342, 658, 426, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 9, 7); +	setHotspot(kHSExitCircus, 100, 590, 700, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9); +	setHotspot(kHSExitCircus, 0, 0, 800, 514); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 5; +} + +void GnapEngine::scene30_run() { +	bool hasTakenPill = false; + +	playSound(0x1093B, 1); +	startSoundTimerB(6); + +	queueInsertDeviceIcon(); + +	if (isFlag(23)) +		_gameSys->insertSequence(0x106, 1, 0, 0, kSeqNone, 0, 0, 0); + +	if (!isFlag(13)) +		_gameSys->insertSequence(0x107, 1, 0, 0, kSeqNone, 0, 0, 0); +	_timers[5] = getRandom(50) + 180; + +	_gameSys->insertSequence(0x101, 40, 0, 0, kSeqNone, 0, 0, 0); +	_timers[4] = getRandom(100) + 300; + +	_s30_dword_47EA88 = 0x101; +	initGnapPos(7, 12, 1); +	initBeaverPos(6, 12, 0); +	endSceneInit(); +	gnapWalkTo(7, 8, -1, 0x107B9, 1); +	platypusWalkTo(6, 8, -1, 0x107C2, 1); + +	while (!_sceneDone) { + +		updateMouseCursor(); +		updateCursorByHotspot(); + +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); + +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene30_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemJoint) { +					gnapUseJointOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan1(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSPillMachine: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemDiceQuarterHole && !isFlag(23)) { +					_hotspots[kHSWalkArea1].flags |= SF_WALKABLE; +					gnapWalkTo(_hotspotsWalkPos[kHSPillMachine].x, _hotspotsWalkPos[kHSPillMachine].y, 0, 0x107BC, 1); +					_hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE; +					_gnapActionStatus = 1; +					hasTakenPill = true; +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSPillMachine].x, _hotspotsWalkPos[kHSPillMachine].y, 8, 5); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						gnapWalkTo(9, 8, 0, 0x107BC, 1); +						_gnapActionStatus = 3; +						break; +					case GRAB_CURSOR: +						playGnapScratchingHead(8, 5); +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(8, 5); +						break; +					} +				} +			} +			break; + +		case kHSExitCircus: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = true; +				if (hasTakenPill) +					_newSceneNum = 47; +				else +					_newSceneNum = 26; +				gnapWalkTo(-1, _hotspotsWalkPos[kHSExitCircus].y, 0, 0x107AE, 1); +				_gnapActionStatus = 0; +				platypusWalkTo(_hotspotsWalkPos[kHSExitCircus].x + 1, _hotspotsWalkPos[kHSExitCircus].y, -1, 0x107C2, 1); +			} +			break; + +		case kHSWalkArea1: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; + +		default: +			if (_mouseClickState.left) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +	 +		} + +		scene30_updateAnimations(); + +		if (!isSoundPlaying(0x1093B)) +			playSound(0x1093B, 1); + +		if (!_isLeavingScene) { +			updateBeaverIdleSequence(); +			if (_gnapActionStatus < 0) +				updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = getRandom(100) + 300; +				if (_gnapActionStatus < 0) { +					if (getRandom(5) == 1) { +						_gameSys->insertSequence(0xFF, 40, 0, 0, kSeqNone, 0, 0, 0); +						_gameSys->insertSequence(0x100, 40, _s30_dword_47EA88, 40, kSeqSyncWait, 0, 0, 0); +						_s30_dword_47EA88 = 0x100; +					} else { +						_gameSys->insertSequence(0xFE, 40, 0, 0, kSeqNone, 0, 0, 0); +					} +				} +			} +			if (!_timers[5]) { +				_timers[5] = getRandom(50) + 180; +				if (_gnapActionStatus < 0) { +					if (!isFlag(23) || hasTakenPill) +						_s30_dword_47EA8C = 0x109; +					else +						_s30_dword_47EA8C = 0x108; +					_gameSys->insertSequence(_s30_dword_47EA8C, 20, 0, 0, kSeqNone, 0, 0, 0); +				} +			} +			playSoundB(); +		} +	 +		checkGameKeys(); +		 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene30_updateHotspots(); +		} +		 +		gameUpdateTick(); + +	} +	 +} + +void GnapEngine::scene30_updateAnimations() { +	 +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case 0: +			_sceneDone = true; +			break; +		case 1: +			setGrabCursorSprite(-1); +			_gameSys->setAnimation(0x105, _gnapId, 0); +			_gameSys->insertSequence(0x105, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x105; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = 2; +			break; +		case 2: +			hideCursor(); +			setGrabCursorSprite(-1); +			addFullScreenSprite(0x3F, 255); +			_gameSys->removeSequence(0x105, _gnapId, 1); +			_gameSys->setAnimation(0x102, 256, 0); +			_gameSys->insertSequence(0x102, 256, 0, 0, kSeqNone, 0, 0, 0); +			while (_gameSys->getAnimationStatus(0) != 2) { +				// checkGameAppStatus(); +				gameUpdateTick(); +			} +			_gameSys->setAnimation(0x103, _gnapId, 0); +			_gameSys->insertSequence(0x103, _gnapId, 0, 0, kSeqNone, 0, 0, 0); +			removeFullScreenSprite(); +			showCursor(); +			_gnapActionStatus = 4; +			invAdd(kItemPill); +			setFlag(23); +			break; +		case 3: +			if (isFlag(23)) +				showFullScreenSprite(0xE3); +			else +				showFullScreenSprite(0xE2); +			_gnapActionStatus = -1; +			break; +		case 4: +			_gameSys->setAnimation(0x104, _gnapId, 0); +			_gameSys->insertSequence(0x104, _gnapId, makeRid(_gnapSequenceDatNum, 0x103), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x104; +			_gnapSequenceDatNum = 0; +			_gnapActionStatus = 5; +			setGrabCursorSprite(kItemDiceQuarterHole); +			break; +		case 5: +			_gameSys->insertSequence(0x106, 1, 0, 0, kSeqNone, 0, 0, 0); +			gnapWalkTo(_hotspotsWalkPos[kHSPillMachine].x, _hotspotsWalkPos[kHSPillMachine].y + 1, -1, 0x107BC, 1); +			_gnapActionStatus = -1; +			break; +		} +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene31.cpp b/engines/gnap/scenes/scene31.cpp new file mode 100644 index 0000000000..864dbf90bc --- /dev/null +++ b/engines/gnap/scenes/scene31.cpp @@ -0,0 +1,398 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus			= 0, +	kHSMeasuringClown	= 1, +	kHSBeerBarrel		= 2, +	kHSDevice			= 3, +	kHSExitCircus		= 4, +	kHSExitOutsideClown	= 5, +	kHSWalkArea1		= 6 +}; + +int GnapEngine::scene31_init() { +	return 0x105; +} + +void GnapEngine::scene31_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSMeasuringClown, 34, 150, 256, 436, SF_WALKABLE | SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 0, 6); +	setHotspot(kHSBeerBarrel, 452, 182, 560, 306, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 7); +	setHotspot(kHSExitCircus, 150, 585, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9); +	setHotspot(kHSExitOutsideClown, 0, 0, 15, 600, SF_EXIT_L_CURSOR | SF_WALKABLE, 0, 8); +	setHotspot(kHSWalkArea1, 0, 0, 800, 480); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 7; +} + +void GnapEngine::scene31_run() { +	 +	playSound(0x1093B, 1); +	startSoundTimerB(6); + +	queueInsertDeviceIcon(); + +	_s31_beerGuyDistracted = false; +	_gameSys->insertSequence(0xFB, 39, 0, 0, kSeqNone, 0, 0, 0); + +	_s31_dword_47EAA8 = 0xFB; +	_s31_dword_47EAAC = -1; + +	_gameSys->setAnimation(0xFB, 39, 3); + +	_timers[4] = getRandom(20) + 60; +	_timers[5] = getRandom(50) + 180; + +	if (_prevSceneNum == 27) { +		initGnapPos(-1, 8, 3); +		initBeaverPos(-1, 9, 4); +		endSceneInit(); +		gnapWalkTo(3, 8, -1, 0x107BA, 1); +		platypusWalkTo(3, 9, -1, 0x107D2, 1); +	} else { +		initGnapPos(7, 12, 1); +		initBeaverPos(6, 12, 0); +		endSceneInit(); +		gnapWalkTo(7, 8, -1, 0x107BA, 1); +		platypusWalkTo(6, 8, -1, 0x107D2, 1); +	} + +	while (!_sceneDone) { + +		updateMouseCursor(); +		updateCursorByHotspot(); + +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); + +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0 || _gnapActionStatus == 4) { +				runMenu(); +				scene31_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex == kItemJoint) { +					gnapUseJointOnPlatypus(); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan1(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSMeasuringClown: +			if (_gnapActionStatus < 0 || _gnapActionStatus == 4) { +				if (_gnapActionStatus == 4) { +					if (_verbCursor == LOOK_CURSOR) +						playGnapScratchingHead(2, 2); +					else +						playGnapImpossible(0, 0); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSMeasuringClown].x, _hotspotsWalkPos[kHSMeasuringClown].y + 1, 2, 2); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(2, 2); +						break; +					case GRAB_CURSOR: +						gnapWalkTo(_hotspotsWalkPos[kHSMeasuringClown].x, _hotspotsWalkPos[kHSMeasuringClown].y + 1, -1, -1, 1); +						_hotspots[kHSWalkArea1].flags |= SF_WALKABLE; +						gnapWalkTo(_hotspotsWalkPos[kHSMeasuringClown].x, _hotspotsWalkPos[kHSMeasuringClown].y, 0, 0x107B9, 1); +						_hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE; +						_gnapActionStatus = 5; +						_timers[4] = 300; +						break; +					case TALK_CURSOR: +						playGnapImpossible(0, 0); +						break; +					case PLAT_CURSOR: +						if (!invHas(kItemBucketWithBeer)) { +							gnapUseDeviceOnBeaver(); +							platypusWalkTo(_hotspotsWalkPos[kHSMeasuringClown].x, _hotspotsWalkPos[kHSMeasuringClown].y + 1, 1, 0x107C2, 1); +							_hotspots[kHSWalkArea1].flags |= SF_WALKABLE; +							platypusWalkTo(_hotspotsWalkPos[kHSMeasuringClown].x, _hotspotsWalkPos[kHSMeasuringClown].y, 1, 0x107C2, 1); +							_hotspots[kHSWalkArea1].flags &= ~SF_WALKABLE; +							_beaverActionStatus = 4; +							_gnapActionStatus = 4; +							_timers[4] = 300; +						} else +							playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSBeerBarrel: +			if (_gnapActionStatus < 0 || _gnapActionStatus == 4) { +				if (_grabCursorSpriteIndex == kItemEmptyBucket && _s31_beerGuyDistracted) { +					setGrabCursorSprite(-1); +					gnapWalkTo(_gnapX, _gnapY, -1, getGnapSequenceId(gskIdle, _hotspotsWalkPos[kHSBeerBarrel].x, _hotspotsWalkPos[kHSBeerBarrel].y) | 0x10000, 1); +					_s31_dword_474940 += 5; +					_gameSys->insertSequence(0xF8, 59, 0, 0, kSeqNone, 0, 0, 0); +					playGnapPullOutDevice(6, 8); +					playGnapUseDevice(0, 0); +					gnapWalkTo(_hotspotsWalkPos[kHSBeerBarrel].x, _hotspotsWalkPos[kHSBeerBarrel].y, 0, 0x107BC, 1); +					_gnapActionStatus = 2; +					_timers[4] = 300; +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSBeerBarrel].x, _hotspotsWalkPos[kHSBeerBarrel].y, 6, 2); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(6, 2); +						break; +					case GRAB_CURSOR: +						if (_s31_beerGuyDistracted) { +							playGnapScratchingHead(6, 2); +						} else { +							gnapWalkTo(_hotspotsWalkPos[kHSBeerBarrel].x, _hotspotsWalkPos[kHSBeerBarrel].y, 0, 0x107BC, 1); +							_gnapActionStatus = 1; +							_gnapIdleFacing = 5; +						} +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSExitCircus: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				_newSceneNum = 26; +				gnapWalkTo(-1, _hotspotsWalkPos[kHSExitCircus].y, 0, 0x107AE, 1); +				_gnapActionStatus = 6; +				platypusWalkTo(_hotspotsWalkPos[kHSExitCircus].x + 1, _hotspotsWalkPos[kHSExitCircus].y, -1, -1, 1); +			} +			break; + +		case kHSExitOutsideClown: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				_newSceneNum = 27; +				gnapWalkTo(-1, _hotspotsWalkPos[kHSExitOutsideClown].y, 0, 0x107AF, 1); +				_gnapActionStatus = 6; +				platypusWalkTo(_hotspotsWalkPos[kHSExitOutsideClown].x, _hotspotsWalkPos[kHSExitOutsideClown].y + 1, -1, 0x107CF, 1); +			} +			break; + +		case kHSWalkArea1: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; + +		default: +			if (_mouseClickState.left) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +		} +	 +		scene31_updateAnimations(); +	 +		if (!isSoundPlaying(0x1093B)) +			playSound(0x1093B, 1); +	 +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0) +				updateBeaverIdleSequence(); +			if (_gnapActionStatus < 0) +				updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = getRandom(20) + 60; +				if (_gnapActionStatus < 0 && _s31_dword_47EAAC == -1) { +					switch (getRandom(6)){ +					case 0: +						_s31_dword_47EAAC = 0xFF; +						break; +					case 1: +						_s31_dword_47EAAC = 0x100; +						break; +					case 2: +						_s31_dword_47EAAC = 0x101; +						break; +					default: +						_s31_dword_47EAAC = 0xFB; +						break; +					} +				} +			} +			if (!_timers[5]) { +				_timers[5] = getRandom(50) + 180; +				if (_gnapActionStatus < 0) { +					if (getRandom(2) != 0) +						_s31_dword_47EAB4 = 0x104; +					else +						_s31_dword_47EAB4 = 0x103; +					_gameSys->insertSequence(_s31_dword_47EAB4, 20, 0, 0, kSeqNone, 0, 0, 0); +				} +			} +			playSoundB(); +		} + +		checkGameKeys(); + +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene31_updateHotspots(); +		} +		 +		gameUpdateTick(); + +	} +	 +} + +void GnapEngine::scene31_updateAnimations() { +	 +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case 1: +			_s31_dword_47EAAC = 0xFE; +			break; +		case 2: +			_gameSys->setAnimation(0x102, 59, 0); +			_gameSys->insertSequence(0x102, 59, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapX = 5; +			_gnapY = 7; +			_gnapSequenceDatNum = 0; +			_gnapSequenceId = 0x102; +			_gnapId = 59; +			_gnapActionStatus = 3; +			break; +		case 3: +			_gnapIdleFacing = 3; +			playGnapPullOutDevice(0, 0); +			playGnapUseDevice(0, 0); +			_gameSys->insertSequence(0xF9, 59, 0xF8, 59, kSeqSyncWait, 0, 0, 0); +			_gnapActionStatus = -1; +			invAdd(kItemBucketWithBeer); +			invRemove(kItemEmptyBucket); +			setGrabCursorSprite(kItemBucketWithBeer); +			break; +		case 5: +			_s31_dword_47EAAC = 0xFA; +			_s31_dword_474940 = 1; +			break; +		case 6: +			_sceneDone = true; +			_gnapActionStatus = -1; +			break; +		} +	} + +	if (_gameSys->getAnimationStatus(1) == 2) { +		_gameSys->setAnimation(0, 0, 1); +		if (_beaverActionStatus == 4) { +			_sceneWaiting = 1; +			_s31_beerGuyDistracted = true; +			_s31_dword_47EAAC = 0xFA; +		} +	} + +	if (_gameSys->getAnimationStatus(3) == 2) { +		switch (_s31_dword_47EAAC) { +		case 0xFA: +			_gameSys->insertSequence(_s31_dword_47EAAC, 39, _s31_dword_47EAA8, 39, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0xFC, 39, _s31_dword_47EAAC, 39, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(0xFC, 39, 3); +			_s31_dword_47EAA8 = 0xFC; +			_s31_dword_47EAAC = 0xFC; +			_s31_dword_47EAB0 = 0; +			break; +		case 0xFC: +			++_s31_dword_47EAB0; +			if (_s31_dword_47EAB0 >= _s31_dword_474940) { +				if (_gnapActionStatus != 5) +					_beaverActionStatus = -1; +				_timers[0] = 40; +				_gameSys->insertSequence(0xFD, 39, _s31_dword_47EAA8, 39, kSeqSyncWait, 0, 0, 0); +				_s31_dword_47EAA8 = 0xFD; +				_s31_dword_47EAAC = -1; +				if (_gnapActionStatus != 3 && _gnapActionStatus != 2) +					_gnapActionStatus = -1; +				_s31_beerGuyDistracted = false; +				_s31_dword_474940 = 3; +				_gameSys->setAnimation(0xFD, 39, 3); +				_sceneWaiting = 0; +			} else { +				_gameSys->insertSequence(_s31_dword_47EAAC, 39, _s31_dword_47EAA8, 39, kSeqSyncWait, 0, 0, 0); +				_s31_dword_47EAA8 = _s31_dword_47EAAC; +				_s31_dword_47EAAC = 0xFC; +				_gameSys->setAnimation(0xFC, 39, 3); +			} +			break; +		case 0xFE: +			_gameSys->insertSequence(_s31_dword_47EAAC, 39, _s31_dword_47EAA8, 39, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s31_dword_47EAAC, 39, 3); +			_s31_dword_47EAA8 = _s31_dword_47EAAC; +			_s31_dword_47EAAC = -1; +			_gnapActionStatus = -1; +			break; +		default: +			if (_s31_dword_47EAAC != -1) { +				_gameSys->insertSequence(_s31_dword_47EAAC, 39, _s31_dword_47EAA8, 39, kSeqSyncWait, 0, 0, 0); +				_gameSys->setAnimation(_s31_dword_47EAAC, 39, 3); +				_s31_dword_47EAA8 = _s31_dword_47EAAC; +				_s31_dword_47EAAC = -1; +			} +			break; +		} +	} +	 +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene32.cpp b/engines/gnap/scenes/scene32.cpp new file mode 100644 index 0000000000..3edd3db2cd --- /dev/null +++ b/engines/gnap/scenes/scene32.cpp @@ -0,0 +1,201 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSExitTruck	= 1, +	kHSDevice		= 2, +	kHSWalkArea1	= 3, +	kHSWalkArea2	= 4, +	kHSWalkArea3	= 5, +	kHSWalkArea4	= 6, +	kHSWalkArea5	= 7, +	kHSWalkArea6	= 8, +	kHSWalkArea7	= 9, +	kHSWalkArea8	= 10 +}; + +int GnapEngine::scene32_init() { +	_gameSys->setAnimation(0, 0, 0); +	return isFlag(26) ? 0xF : 0x10; +} + +void GnapEngine::scene32_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitTruck, 780, 226, 800, 455, SF_EXIT_R_CURSOR | SF_WALKABLE, 10, 6); +	setHotspot(kHSWalkArea1, 0, 0, 162, 426); +	setHotspot(kHSWalkArea2, 162, 0, 237, 396); +	setHotspot(kHSWalkArea3, 237, 0, 319, 363); +	setHotspot(kHSWalkArea4, 520, 0, 800, 404); +	setHotspot(kHSWalkArea5, 300, 447, 800, 600); +	setHotspot(kHSWalkArea6, 678, 0, 800, 404); +	setHotspot(kHSWalkArea7, 0, 0, 520, 351); +	setHotspot(kHSWalkArea8, 0, 546, 300, 600); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 11; +} + +void GnapEngine::scene32_run() { +	 +	playSound(0x1091C, 1); +	startSoundTimerC(5); +	queueInsertDeviceIcon(); +	_s32_dword_47EADC = -1; +	_timers[4] = getRandom(100) + 300; + +	if (_prevSceneNum == 33) { +		initGnapPos(11, 6, 3); +		initBeaverPos(12, 6, 4); +		endSceneInit(); +		platypusWalkTo(9, 6, -1, 0x107D2, 1); +		gnapWalkTo(8, 6, -1, 0x107BA, 1); +	} else { +		initGnapPos(1, 6, 1); +		initBeaverPos(1, 7, 0); +		endSceneInit(); +	} +	 +	while (!_sceneDone) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +		testWalk(0, 0, -1, -1, -1, -1); +		 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene32_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(_platX, _platY); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan1(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(_platX, _platY); +						break; +					} +				} +			} +			break; + +		case kHSExitTruck: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				setGrabCursorSprite(-1); +				gnapWalkTo(_hotspotsWalkPos[kHSExitTruck].x, _hotspotsWalkPos[kHSExitTruck].y, 0, 0x107AB, 1); +				_gnapActionStatus = 0; +				platypusWalkTo(_hotspotsWalkPos[kHSExitTruck].x, _hotspotsWalkPos[kHSExitTruck].y + 1, -1, 0x107CD, 1); +				_newSceneNum = 33; +			} +			break; + +		case kHSWalkArea1: +		case kHSWalkArea2: +		case kHSWalkArea3: +		case kHSWalkArea4: +		case kHSWalkArea5: +		case kHSWalkArea6: +		case kHSWalkArea7: +		case kHSWalkArea8: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; + +		} + +		if (_mouseClickState.left && _gnapActionStatus < 0) { +			gnapWalkTo(-1, -1, -1, -1, 1); +			_mouseClickState.left = 0; +		} + +		scene32_updateAnimations(); +		 +		if (!isSoundPlaying(0x1091C)) +			playSound(0x1091C, 1); +	 +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0) +				updateBeaverIdleSequence(); +			if (_gnapActionStatus < 0) +				updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = getRandom(100) + 300; +				if (getRandom(2) != 0) +					_s32_dword_47EADC = 14; +				else +					_s32_dword_47EADC = 13; +				_gameSys->insertSequence(_s32_dword_47EADC, 180, 0, 0, kSeqNone, 0, 0, 0); +			} +			playSoundC(); +		} +	 +		checkGameKeys(); +		 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene32_updateHotspots(); +		} +		 +		gameUpdateTick(); +	 +	} +	 +} + +void GnapEngine::scene32_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		if (_gnapActionStatus == 0) +			_sceneDone = true; +	} + +} + +} // End of namespace Gnap +					
\ No newline at end of file diff --git a/engines/gnap/scenes/scene33.cpp b/engines/gnap/scenes/scene33.cpp new file mode 100644 index 0000000000..f9471abcd5 --- /dev/null +++ b/engines/gnap/scenes/scene33.cpp @@ -0,0 +1,327 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSChicken		= 1, +	kHSDevice		= 2, +	kHSExitHouse	= 3, +	kHSExitBarn		= 4, +	kHSExitCreek	= 5, +	kHSExitPigpen	= 6, +	kHSWalkArea1	= 7, +	kHSWalkArea2	= 8 +}; + +int GnapEngine::scene33_init() { +	return isFlag(26) ? 0x84 : 0x85; +} + +void GnapEngine::scene33_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSChicken, 606, 455, 702, 568, SF_WALKABLE | SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 8); +	setHotspot(kHSExitHouse, 480, 120, 556, 240, SF_EXIT_U_CURSOR, 7, 3); +	setHotspot(kHSExitBarn, 610, 75, 800, 164, SF_EXIT_U_CURSOR, 10, 3); +	setHotspot(kHSExitCreek, 780, 336, 800, 556, SF_EXIT_R_CURSOR | SF_WALKABLE, 10, 8); +	setHotspot(kHSExitPigpen, 0, 300, 20, 600, SF_EXIT_L_CURSOR | SF_WALKABLE, 0, 8); +	setHotspot(kHSWalkArea1, 120, 0, 514, 458); +	setHotspot(kHSWalkArea2, 0, 0, 800, 452); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 9; +} + +void GnapEngine::scene33_run() { +	 +	playSound(0x1091C, 1); +	startSoundTimerC(6); +	queueInsertDeviceIcon(); + +	_s33_dword_47EAEC = 0x7E; +	_gameSys->setAnimation(0x7E, 179, 2); +	_gameSys->insertSequence(_s33_dword_47EAEC, 179, 0, 0, kSeqNone, 0, 0, 0); +	_s33_dword_47EAE4 = -1; +	_timers[5] = getRandom(20) + 30; +	_s33_dword_47EAE8 = -1; +	_timers[4] = getRandom(100) + 300; + +	switch (_prevSceneNum) { +	case 34: +		initGnapPos(11, 7, 3); +		initBeaverPos(12, 7, 4); +		endSceneInit(); +		gnapWalkTo(8, 7, -1, 0x107BA, 1); +		platypusWalkTo(9, 7, -1, 0x107D2, 1); +		break; +	case 37: +		initGnapPos(7, 7, 1); +		initBeaverPos(8, 7, 0); +		endSceneInit(); +		break; +	case 32: +		initGnapPos(-1, 6, 1); +		initBeaverPos(-1, 7, 0); +		endSceneInit(); +		platypusWalkTo(2, 7, -1, 0x107C2, 1); +		gnapWalkTo(2, 8, -1, 0x107B9, 1); +		break; +	default: +		initGnapPos(3, 7, 1); +		initBeaverPos(2, 7, 0); +		endSceneInit(); +		break; +	} + +	while (!_sceneDone) { + +		updateMouseCursor(); +		updateCursorByHotspot(); +		testWalk(0, 0, 7, 6, 8, 6); +		 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene33_updateHotspots(); +			} +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(_platX, _platY); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan1(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(_platX, _platY); +						break; +					} +				} +			} +			break; + +		case kHSChicken: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(7, 9, 9, 8); +				} else { +					switch (_verbCursor) { +					case GRAB_CURSOR: +						_gnapIdleFacing = 1; +						if (gnapWalkTo(_hotspotsWalkPos[kHSChicken].x, _hotspotsWalkPos[kHSChicken].y, 0, getGnapSequenceId(gskIdle, 0, 0) | 0x10000, 1)) +							_gnapActionStatus = 2; +						else +							_gnapActionStatus = -1; +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 1; +						gnapWalkTo(_hotspotsWalkPos[kHSChicken].x, _hotspotsWalkPos[kHSChicken].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = 1; +						break; +					case LOOK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +	 +		case kHSExitHouse: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				_gnapActionStatus = 0; +				_newSceneNum = 37; +				if (_gnapX > 6) +					gnapWalkTo(_gnapX, _gnapY, 0, 0x107AD, 1); +				else +					gnapWalkTo(6, 7, 0, 0x107B1, 1); +			} +			break; +	 +		case kHSExitBarn: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				_gnapActionStatus = 0; +				_newSceneNum = 35; +				if (_gnapX > 7) +					gnapWalkTo(_gnapX, _gnapY, 0, 0x107AD, 1); +				else +					gnapWalkTo(7, 7, 0, 0x107B1, 1); +			} +			break; + +		case kHSExitCreek: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[kHSExitCreek].x, _hotspotsWalkPos[kHSExitCreek].y, 0, 0x107AB, 1); +				_gnapActionStatus = 0; +				platypusWalkTo(_hotspotsWalkPos[kHSExitCreek].x, _hotspotsWalkPos[kHSExitCreek].y, -1, 0x107CD, 1); +				_newSceneNum = 34; +			} +			break; +	 +		case kHSExitPigpen: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[kHSExitPigpen].x, _hotspotsWalkPos[kHSExitPigpen].y, 0, 0x107AF, 1); +				_gnapActionStatus = 0; +				platypusWalkTo(_hotspotsWalkPos[kHSExitPigpen].x, _hotspotsWalkPos[kHSExitPigpen].y, -1, 0x107CF, 1); +				_newSceneNum = 32; +			} +			break; +	 +		case kHSWalkArea1: +		case kHSWalkArea2: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; +			 +		default: +			if (_mouseClickState.left && _gnapActionStatus < 0) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; + +		} +	 +		scene33_updateAnimations(); +	 +		if (!isSoundPlaying(0x1091C)) +			playSound(0x1091C, 1); +	 +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0) +				updateBeaverIdleSequence(); +			if (_gnapActionStatus < 0) +				updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = getRandom(100) + 300; +				if (getRandom(2) != 0) +					_s33_dword_47EAE8 = 0x83; +				else +					_s33_dword_47EAE8 = 0x82; +				_gameSys->insertSequence(_s33_dword_47EAE8, 256, 0, 0, kSeqNone, 0, 0, 0); +			} +			if (!_timers[5] && _s33_dword_47EAE4 == -1 && _gnapActionStatus != 1 && _gnapActionStatus != 2) { +				if (getRandom(6) != 0) { +					_s33_dword_47EAE4 = 0x7E; +					_timers[5] = getRandom(20) + 30; +				} else { +					_s33_dword_47EAE4 = 0x80; +					_timers[5] = getRandom(20) + 50; +				} +			} +			playSoundC(); +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene33_updateHotspots(); +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene33_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		switch (_gnapActionStatus) { +		case 0: +			_sceneDone = true; +			break; +		case 1: +			_s33_dword_47EAE4 = 0x7F; +			break; +		case 2: +			_s33_dword_47EAE4 = 0x81; +			_timers[2] = 100; +			break; +		case 3: +			_gameSys->insertSequence(0x107B5, _gnapId, 0x81, 179, kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +			_gnapSequenceId = 0x7B5; +			_gnapSequenceDatNum = 1; +			_s33_dword_47EAEC = 0x7E; +			_gameSys->setAnimation(0x7E, 179, 2); +			_gameSys->insertSequence(_s33_dword_47EAEC, 179, 0, 0, kSeqNone, 0, 0, 0); +			_gnapActionStatus = -1; +			_timers[5] = 30; +			break; +		default: +			_gnapActionStatus = -1; +			break; +		} +	} + +	if (_gameSys->getAnimationStatus(2) == 2) { +		if (_s33_dword_47EAE4 == 0x81) { +			_gameSys->setAnimation(_s33_dword_47EAE4, 179, 0); +			_gameSys->insertSequence(_s33_dword_47EAE4, 179, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gameSys->removeSequence(_s33_dword_47EAEC, 179, 1); +			_s33_dword_47EAE4 = -1; +			_s33_dword_47EAEC = -1; +			_gnapActionStatus = 3; +			_timers[5] = 500; +		} else if (_s33_dword_47EAE4 == 0x7F) { +			_gameSys->setAnimation(_s33_dword_47EAE4, 179, 2); +			_gameSys->insertSequence(_s33_dword_47EAE4, 179, _s33_dword_47EAEC, 179, kSeqSyncWait, 0, 0, 0); +			_s33_dword_47EAEC = _s33_dword_47EAE4; +			_s33_dword_47EAE4 = -1; +			_gnapActionStatus = -1; +		} else if (_s33_dword_47EAE4 != -1) { +			_gameSys->setAnimation(_s33_dword_47EAE4, 179, 2); +			_gameSys->insertSequence(_s33_dword_47EAE4, 179, _s33_dword_47EAEC, 179, kSeqSyncWait, 0, 0, 0); +			_s33_dword_47EAEC = _s33_dword_47EAE4; +			_s33_dword_47EAE4 = -1; +		} +	} + +} + +} // End of namespace Gnap +					
\ No newline at end of file diff --git a/engines/gnap/scenes/scene38.cpp b/engines/gnap/scenes/scene38.cpp new file mode 100644 index 0000000000..cfbaf9dcaf --- /dev/null +++ b/engines/gnap/scenes/scene38.cpp @@ -0,0 +1,355 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus			= 0, +	kHSExitHouse		= 1, +	kHSExitCave			= 2, +	kHSTrapDoorLid1		= 3, +	kHSTrapDoorLid2		= 4, +	kHSHuntingTrophy	= 5, +	kHSWalkArea1		= 6, +	kHSDevice			= 7, +	kHSWalkArea2		= 8, +	kHSWalkArea3		= 9, +	kHSWalkArea4		= 10, +	kHSWalkArea5		= 11, +	kHSWalkArea6		= 12 +}; + +int GnapEngine::scene38_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	return 0xA5; +} + +void GnapEngine::scene38_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitHouse, 150, 585, 650, 600, SF_EXIT_D_CURSOR, 0, 8); +	setHotspot(kHSExitCave, 430, 440, 655, 470, SF_WALKABLE, 0, 8); +	setHotspot(kHSTrapDoorLid1, 525, 265, 640, 350, SF_DISABLED); +	setHotspot(kHSTrapDoorLid2, 555, 350, 670, 430, SF_DISABLED); +	setHotspot(kHSHuntingTrophy, 170, 85, 250, 190, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 0, 8); +	setHotspot(kHSWalkArea1, 330, 270, 640, 380, SF_DISABLED | SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 0, 8); +	setHotspot(kHSWalkArea2, 0, 0, 799, 396); +	setHotspot(kHSWalkArea3, 0, 585, 799, 599, SF_WALKABLE | SF_DISABLED); +	setHotspot(kHSWalkArea4, 0, 0, 97, 445); +	setHotspot(kHSWalkArea5, 770, 0, 799, 445); +	setHotspot(kHSWalkArea6, 393, 0, 698, 445, SF_WALKABLE | SF_DISABLED); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	if (_beaverActionStatus == 6) +		_hotspots[kHSPlatypus].flags = SF_WALKABLE | SF_DISABLED; +	if (_beaverActionStatus == 6) +		_hotspots[kHSExitCave].flags = SF_EXIT_D_CURSOR; +	else if (_gnapActionStatus == 3) +		_hotspots[kHSExitCave].flags = SF_EXIT_D_CURSOR; +	if (_beaverActionStatus == 6) +		_hotspots[kHSTrapDoorLid1].flags = SF_DISABLED; +	else if (_gnapActionStatus == 3) +		_hotspots[kHSTrapDoorLid1].flags = SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR; +	if (_beaverActionStatus == 6) +		_hotspots[kHSTrapDoorLid2].flags = SF_DISABLED; +	else if (_gnapActionStatus == 3) +		_hotspots[kHSTrapDoorLid2].flags = SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR; +	if (_beaverActionStatus == 6) +		_hotspots[kHSWalkArea6].flags = 0; +	_hotspotsCount = 13; +} + +void GnapEngine::scene38_run() { + +	queueInsertDeviceIcon(); +	_gameSys->insertSequence(0x9B, 0, 0, 0, kSeqNone, 0, 0, 0); +	 +	if (_prevSceneNum == 39) { +		initGnapPos(3, 7, 3); +		initBeaverPos(4, 7, 4); +	} else { +		initGnapPos(3, 8, 1); +		initBeaverPos(4, 8, 0); +	} +	endSceneInit(); + +	while (!_sceneDone) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); + +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			runMenu(); +			scene38_updateHotspots(); +			break; + +		case kHSPlatypus: +			if (_gnapActionStatus == 3) { +				_gnapActionStatus = 4; +			} else if (_grabCursorSpriteIndex >= 0) { +				playGnapImpossible(_platX, _platY); +			} else { +				switch (_verbCursor) { +				case LOOK_CURSOR: +					playGnapMoan1(_platX, _platY); +					break; +				case GRAB_CURSOR: +					gnapKissPlatypus(0); +					break; +				case TALK_CURSOR: +					playGnapBrainPulsating(_platX, _platY); +					playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +					break; +				case PLAT_CURSOR: +					playGnapImpossible(_platX, _platY); +					break; +				} +			} +			break; + +		case kHSExitHouse: +			if (_gnapActionStatus == 3) { +				_gnapActionStatus = 4; +			} else { +				_isLeavingScene = 1; +				gnapWalkTo(-1, -1, 0, 0x107AE, 1); +				_gnapActionStatus = 0; +				_newSceneNum = 37; +			} +			break; + +		case kHSExitCave: +			if (_gnapActionStatus == 3) { +				_gnapActionStatus = 4; +				if (_beaverActionStatus == 6) +					_isLeavingScene = 1; +			} else if (_beaverActionStatus == 6) { +				_sceneWaiting = 0; +				_isLeavingScene = 1; +				gnapWalkTo(5, 7, 0, 0x107BB, 1); +				_newSceneNum = 39; +				_gnapActionStatus = 1; +			} +			break; + +		case kHSTrapDoorLid1: +		case kHSTrapDoorLid2: +			if (_gnapActionStatus == 3) { +				if (_beaverActionStatus == 6 && _verbCursor == PLAT_CURSOR) +					_gnapActionStatus = 5; +				else +					_gnapActionStatus = 4; +			} +			break; + +		case kHSHuntingTrophy: +			if (_gnapActionStatus != 3) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(3, 6, 2, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(0, 0); +						break; +					case GRAB_CURSOR: +						if (_beaverActionStatus == 6) +							playGnapImpossible(0, 0); +						else { +							gnapWalkTo(3, 6, 0, 0x107BB, 1); +							platypusWalkTo(4, 8, -1, -1, 1); +							_gnapActionStatus = 2; +						} +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(2, 0); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; + +		case kHSWalkArea1: +			// Nothing +			break; + +		case kHSWalkArea2: +		case kHSWalkArea3: +		case kHSWalkArea4: +		case kHSWalkArea5: +		case kHSWalkArea6: +			if (_gnapActionStatus == 3) +				_gnapActionStatus = 4; +			else if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; +			 +		default: +			if (_mouseClickState.left) { +				if (_gnapActionStatus == 3) +					_gnapActionStatus = 4; +				else if (_gnapActionStatus < 0) +					gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; + +		} + +		scene38_updateAnimations(); +	 +		if (!_isLeavingScene) { +			updateBeaverIdleSequence(); +			updateGnapIdleSequence(); +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene38_updateHotspots(); +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene38_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case 0: +			_sceneDone = true; +			break; +		case 1: +			_gameSys->removeSequence(_beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, 1); +			_gameSys->insertSequence(0xA3, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0xA3; +			_gnapSequenceDatNum = 0; +			_gameSys->setAnimation(0xA3, _gnapId, 0); +			_gnapActionStatus = 0; +			break; +		case 2: +			_gameSys->removeSequence(0x9B, 0, 1); +			_gameSys->insertSequence(0x9C, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x9C; +			_gnapSequenceDatNum = 0; +			_gameSys->setAnimation(0x9C, _gnapId, 0); +			_gnapActionStatus = 3; +			scene38_updateHotspots(); +			break; +		case 3: +			if (_beaverActionStatus != 6) +				_sceneWaiting = 1; +			if (_gnapSequenceId == 0xA4) { +				_gameSys->insertSequence(0x9D, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +				_gnapSequenceId = 0x9D; +			} else { +				_gameSys->insertSequence(0xA4, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +				_gnapSequenceId = 0xA4; +			} +			_gnapSequenceDatNum = 0; +			_gameSys->setAnimation(_gnapSequenceId, _gnapId, 0); +			break; +		case 4: +			if (_gnapSequenceId == 0x9E) { +				_gameSys->insertSequence(0x9B, 0, 0, 0, kSeqNone, 0, 0, 0); +				_gnapActionStatus = -1; +			} else if (_beaverActionStatus == 6) { +				_gameSys->insertSequence(0xA0, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +				_gnapSequenceId = 0xA0; +				_gnapSequenceDatNum = 0; +				_gnapX = 3; +				_gnapY = 6; +				_gnapIdleFacing = 1; +				if (_isLeavingScene) { +					_sceneWaiting = 0; +					gnapWalkTo(5, 7, 0, 0x107BB, 1); +					_newSceneNum = 39; +					_gnapActionStatus = 1; +				} else { +					_gnapActionStatus = -1; +				} +			} else { +				_gameSys->insertSequence(0x9E, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +				_gnapSequenceId = 0x9E; +				_gnapSequenceDatNum = 0; +				_gnapX = 3; +				_gnapY = 6; +				_gnapIdleFacing = 1; +				_gameSys->setAnimation(0x9E, _gnapId, 0); +				_sceneWaiting = 0; +				scene38_updateHotspots(); +			} +			break; +		case 5: +			_sceneWaiting = 0; +			_gameSys->insertSequence(0x9F, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x9F; +			_gnapSequenceDatNum = 0; +			_gameSys->setAnimation(0x9F, _gnapId, 0); +			_gnapActionStatus = 3; +			if (_beaverFacing) +				playBeaverSequence(0x107D5); +			else +				playBeaverSequence(0x107D4); +			platypusWalkTo(8, 7, -1, 0x107D2, 1); +			_gameSys->insertSequence(0xA1, _gnapId + 1, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0); +			_beaverSequenceId = 0xA1; +			_beaverSequenceDatNum = 0; +			_beaverId = _gnapId + 1; +			_gameSys->setAnimation(0xA1, _gnapId + 1, 1); +			_beaverActionStatus = 6; +			scene38_updateHotspots(); +			break; +		} +	} + +	if (_gameSys->getAnimationStatus(1) == 2) { +		_gameSys->setAnimation(0, 0, 1); +		if (_beaverActionStatus == 6) { +			_gameSys->insertSequence(0xA2, _beaverId, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0); +			_beaverSequenceId = 0xA2; +			_beaverSequenceDatNum = 0; +			scene38_updateHotspots(); +			_sceneWaiting = true; +		} +	} + +} + +} // End of namespace Gnap +					
\ No newline at end of file diff --git a/engines/gnap/scenes/scene39.cpp b/engines/gnap/scenes/scene39.cpp new file mode 100644 index 0000000000..7bf04de240 --- /dev/null +++ b/engines/gnap/scenes/scene39.cpp @@ -0,0 +1,237 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus			= 0, +	kHSExitInsideHouse	= 1, +	kHSExitUfoParty		= 2, +	kHSSign				= 3, +	kHSDevice			= 4, +	kHSWalkArea1		= 5, +	kHSWalkArea2		= 6 +}; + +int GnapEngine::scene39_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	return 0x35; +} + +void GnapEngine::scene39_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitInsideHouse, 0, 0, 140, 206, SF_EXIT_U_CURSOR, 4, 8); +	setHotspot(kHSExitUfoParty, 360, 204, 480, 430, SF_EXIT_R_CURSOR, 6, 8); +	setHotspot(kHSSign, 528, 232, 607, 397, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 3); +	setHotspot(kHSWalkArea1, 0, 0, 800, 466); +	setHotspot(kHSWalkArea2, 502, 466, 800, 600); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 7; +} + +void GnapEngine::scene39_run() { +	 +	queueInsertDeviceIcon(); +	_s39_dword_47EAF8 = 0x33; + +	_gameSys->setAnimation(0x33, 21, 3); +	_gameSys->insertSequence(_s39_dword_47EAF8, 21, 0, 0, kSeqNone, 0, 0, 0); +	_gameSys->insertSequence(0x34, 21, 0, 0, kSeqLoop, 0, 0, 0); + +	_s39_dword_47EAFC = -1; +	if (_prevSceneNum == 38) { +		initGnapPos(3, 7, 7); +		initBeaverPos(2, 7, 5); +		endSceneInit(); +	} else { +		initGnapPos(4, 7, 1); +		initBeaverPos(5, 7, 0); +		endSceneInit(); +	} +	 +	while (!_sceneDone) { + +		if (!isSoundPlaying(0x1094B)) { +			playSound(0x1094B, 1); +			setSoundVolume(0x1094B, 60); +		} + +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 0, -1, -1, -1, -1); + +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); + +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			runMenu(); +			scene39_updateHotspots(); +			_timers[5] = getRandom(20) + 50; +			break; +	 +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(_platX, _platY); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan1(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(_platX, _platY); +						break; +					} +				} +			} +			break; +	 +		case kHSExitUfoParty: +			if (_gnapActionStatus < 0) { +				_isLeavingScene = 1; +				_sceneDone = true; +				gnapWalkTo(_gnapX, _gnapY, 0, 0x107AB, 1); +				_gnapActionStatus = 0; +				_newSceneNum = 40; +			} +			break; +	 +		case kHSSign: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(0, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						gnapWalkTo(_hotspotsWalkPos[kHSSign].x, _hotspotsWalkPos[kHSSign].y, 0, -1, 1); +						playGnapIdle(_hotspotsWalkPos[kHSSign].x, _hotspotsWalkPos[kHSSign].y); +						showFullScreenSprite(0x1C); +						break; +					case GRAB_CURSOR: +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +			} +			break; +	 +		case kHSExitInsideHouse: +			if (_gnapActionStatus < 0) { +				_sceneDone = true; +				_isLeavingScene = 1; +				_newSceneNum = 38; +			} +			break; +	 +		case kHSWalkArea1: +		case kHSWalkArea2: +			if (_gnapActionStatus < 0) +				gnapWalkTo(-1, -1, -1, -1, 1); +			break; +			 +		default: +			if (_mouseClickState.left && _gnapActionStatus < 0) { +				gnapWalkTo(-1, -1, -1, -1, 1); +				_mouseClickState.left = false; +			} +			break; +			 +		} +	 +		scene39_updateAnimations(); +	 +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0) +				updateBeaverIdleSequence(); +			if (_gnapActionStatus < 0) +				updateGnapIdleSequence(); +			if (!_timers[5]) { +				_timers[5] = getRandom(20) + 50; +				switch (getRandom(4)) { +				case 0: +					_s39_dword_47EAFC = 0x30; +					break; +				case 1: +					_s39_dword_47EAFC = 0x31; +					break; +				case 2: +					_s39_dword_47EAFC = 0x32; +					break; +				case 3: +					_s39_dword_47EAFC = 0x33; +					break; +				} +			} +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene39_updateHotspots(); +			_timers[5] = getRandom(20) + 50; +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene39_updateAnimations() { +	 +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		if (_gnapActionStatus == 0) +			_sceneDone = true; +		else +			_gnapActionStatus = -1; +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2 && _s39_dword_47EAFC != -1) { +		_gameSys->setAnimation(_s39_dword_47EAFC, 21, 3); +		_gameSys->insertSequence(_s39_dword_47EAFC, 21, _s39_dword_47EAF8, 21, kSeqSyncWait, 0, 0, 0); +		_s39_dword_47EAF8 = _s39_dword_47EAFC; +		_s39_dword_47EAFC = -1; +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene40.cpp b/engines/gnap/scenes/scene40.cpp new file mode 100644 index 0000000000..fe91dbf777 --- /dev/null +++ b/engines/gnap/scenes/scene40.cpp @@ -0,0 +1,193 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus			= 0, +	kHSExitCave			= 1, +	kHSExitToyStand		= 2, +	kHSExitBBQ			= 3, +	kHSExitUfo			= 4, +	kHSExitKissinBooth	= 5, +	kHSExitDancefloor	= 6, +	kHSExitShoe			= 7, +	kHSDevice			= 8 +}; + +int GnapEngine::scene40_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	return isFlag(23) ? 0x01 : 0x00; +} + +void GnapEngine::scene40_updateHotspots() { +	setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_DISABLED | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(kHSExitCave, 169, 510, 264, 600, SF_EXIT_D_CURSOR, 0, 8); +	setHotspot(kHSExitToyStand, 238, 297, 328, 376, SF_EXIT_L_CURSOR, 0, 8); +	setHotspot(kHSExitBBQ, 328, 220, 401, 306, SF_EXIT_L_CURSOR, 0, 8); +	setHotspot(kHSExitUfo, 421, 215, 501, 282, SF_EXIT_U_CURSOR, 0, 8); +	setHotspot(kHSExitKissinBooth, 476, 284, 556, 345, SF_EXIT_R_CURSOR, 0, 8); +	setHotspot(kHSExitDancefloor, 317, 455, 445, 600, SF_EXIT_D_CURSOR, 0, 8); +	setHotspot(kHSExitShoe, 455, 346, 549, 417, SF_EXIT_D_CURSOR, 0, 8); +	setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +	_hotspotsCount = 9; +} + +void GnapEngine::scene40_run() { + +	queueInsertDeviceIcon(); +	endSceneInit(); + +	while (!_sceneDone) { + +		if (!isSoundPlaying(0x1094B)) +			playSound(0x1094B, 1); + +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 0, -1, -1, -1, -1); + +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { + +		case kHSDevice: +			runMenu(); +			scene40_updateHotspots(); +			break; +			 +		case kHSPlatypus: +			if (_gnapActionStatus < 0) { +				if (_grabCursorSpriteIndex >= 0) { +					playGnapImpossible(_platX, _platY); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan1(_platX, _platY); +						break; +					case GRAB_CURSOR: +						gnapKissPlatypus(0); +						break; +					case TALK_CURSOR: +						playGnapBrainPulsating(_platX, _platY); +						playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(_platX, _platY); +						break; +					} +				} +			} +			break; +	 +		case kHSExitCave: +			if (_gnapActionStatus < 0) { +				_newSceneNum = 39; +				_sceneDone = true; +			} +			break; +	 +		case kHSExitToyStand: +			if (_gnapActionStatus < 0) { +				_newSceneNum = 41; +				_sceneDone = true; +			} +			break; +	 +		case kHSExitBBQ: +			if (_gnapActionStatus < 0) { +				_newSceneNum = 42; +				_sceneDone = true; +			} +			break; +	 +		case kHSExitUfo: +			if (_gnapActionStatus < 0) { +				_newSceneNum = 43; +				_sceneDone = true; +			} +			break; +	 +		case kHSExitKissinBooth: +			if (_gnapActionStatus < 0) { +				_newSceneNum = 44; +				_sceneDone = true; +			} +			break; +	 +		case kHSExitDancefloor: +			if (_gnapActionStatus < 0) { +				_newSceneNum = 45; +				_sceneDone = true; +			} +			break; +	 +		case kHSExitShoe: +			if (_gnapActionStatus < 0) { +				_newSceneNum = 46; +				_sceneDone = true; +			} +			break; +	 +		default: +			if (_mouseClickState.left && _gnapActionStatus < 0) +				_mouseClickState.left = false; +			break; +		 +		} +	 +		scene40_updateAnimations(); +		 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene40_updateHotspots(); +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene40_updateAnimations() { +	 +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		if (_gnapActionStatus) +			_gnapActionStatus = -1; +		else +			_sceneDone = true; +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene41.cpp b/engines/gnap/scenes/scene41.cpp new file mode 100644 index 0000000000..60c5979ae7 --- /dev/null +++ b/engines/gnap/scenes/scene41.cpp @@ -0,0 +1,577 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSExitCave		= 1, +	kHSExit			= 2, +	kHSExitBBQ		= 3, +	kHSToyVendor	= 4, +	kHSKid			= 5, +	kHSToyUfo		= 6, +	kHSDevice		= 7, +	kHSWalkArea1	= 8 +}; + +enum { +	kHSUfoExitLeft	= 1, +	kHSUfoExitRight	= 2, +	kHSUfoDevice	= 3, +	kHSUfoWalkArea1	= 4 +}; + +int GnapEngine::scene41_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	_gameSys->setAnimation(0, 0, 2); +	return 0x129; +} + +void GnapEngine::scene41_updateHotspots() { +	if (isFlag(12)) { +		setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED); +		setHotspot(kHSUfoExitLeft, 0, 0, 10, 500, SF_EXIT_L_CURSOR | SF_DISABLED); +		setHotspot(kHSUfoExitRight, 790, 0, 799, 500, SF_EXIT_R_CURSOR); +		setHotspot(kHSUfoWalkArea1, 0, 0, 800, 470, SF_DISABLED); +		setDeviceHotspot(kHSUfoDevice, -1, -1, -1, -1); +		_hotspotsCount = 5; +	} else { +		setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +		setHotspot(kHSExitCave, 150, 590, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9); +		setHotspot(kHSExit, 0, 100, 10, 599, SF_EXIT_L_CURSOR | SF_DISABLED, 0, 8); +		setHotspot(kHSExitBBQ, 790, 100, 799, 599, SF_EXIT_R_CURSOR | SF_WALKABLE, 10, 8); +		setHotspot(kHSToyVendor, 320, 150, 430, 310, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +		setHotspot(kHSKid, 615, 340, 710, 460, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +		setHotspot(kHSToyUfo, 0, 0, 0, 0, SF_GRAB_CURSOR); +		setHotspot(kHSWalkArea1, 0, 0, 800, 470); +		setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +		_hotspotsCount = 9; +	} +} + +void GnapEngine::scene41_run() { + +	queueInsertDeviceIcon(); + +	if (isFlag(12)) { +		_toyUfoX = 770; +		if (_toyUfoY < 0 || _toyUfoY > 300) +			_toyUfoY = 150; +		if (!_timers[9]) +			_gnapActionStatus = 6; +	} else { +		if (!isFlag(16) && !isFlag(17) && !isFlag(18) && !isFlag(19)) +			toyUfoSetStatus(16); +		_toyUfoX = 600; +		_toyUfoY = 200; +	} + +	_toyUfoId = 0; +	_toyUfoActionStatus = -1; +	_toyUfoSequenceId = toyUfoGetSequenceId(); +	_toyUfoNextSequenceId = _toyUfoSequenceId; + +	_gameSys->setAnimation(_toyUfoSequenceId | 0x10000, _toyUfoId, 2); +	_gameSys->insertSequence(_toyUfoSequenceId | 0x10000, _toyUfoId, 0, 0, kSeqNone, 0, _toyUfoX - 274, _toyUfoY - 128); +	_gameSys->insertSequence(0x128, 0, 0, 0, kSeqLoop, 0, 0, 0); +	 +	if (isFlag(12)) +		_s41_dword_47F2C4 = 0x11B; +	else +		_s41_dword_47F2C4 = 0x11D; +	 +	_s41_dword_47F2C0 = -1; +	 +	_gameSys->setAnimation(_s41_dword_47F2C4, 1, 4); +	_gameSys->insertSequence(_s41_dword_47F2C4, 1, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s41_dword_47F2CC = 0x118; +	_s41_dword_47F2C8 = -1; +	 +	_gameSys->setAnimation(0x118, 1, 3); +	_gameSys->insertSequence(_s41_dword_47F2CC, 1, 0, 0, kSeqNone, 0, 0, 0); +	_gameSys->insertSequence(0x127, 2, 0, 0, kSeqNone, 0, 0, 0); +	 +	if (isFlag(12)) { +		_gnapSequenceId = 0x120; +		_gnapSequenceDatNum = 0; +		_gnapIdleFacing = 7; +		_gnapX = 7; +		_gnapY = 7; +		_gnapId = 140; +		_gameSys->insertSequence(0x120, 140, 0, 0, kSeqNone, 0, 0, 0); +		_gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0); +		initBeaverPos(8, 10, 3); +		endSceneInit(); +	} else if (_prevSceneNum == 45) { +		initGnapPos(-1, 8, 7); +		initBeaverPos(-2, 8, 5); +		endSceneInit(); +		platypusWalkTo(1, 8, -1, 0x107C2, 1); +		gnapWalkTo(2, 8, -1, 0x107B9, 1); +	} else if (_prevSceneNum == 42) { +		initGnapPos(11, 8, 7); +		initBeaverPos(11, 9, 5); +		endSceneInit(); +		gnapWalkTo(8, 8, -1, 0x107BA, 1); +		platypusWalkTo(9, 8, -1, 0x107D2, 1); +	} else { +		initGnapPos(5, 8, 1); +		initBeaverPos(6, 8, 3); +		endSceneInit(); +	} + +	_timers[4] = getRandom(100) + 100; +	_timers[5] = getRandom(30) + 20; + +	while (!_sceneDone) { +	 +		if (!isSoundPlaying(0x1094B)) +			playSound(0x1094B, 1); +	 +		if (!isFlag(12)) { +			_hotspots[kHSToyUfo].x1 = _toyUfoX - 25; +			_hotspots[kHSToyUfo].y1 = _toyUfoY - 20; +			_hotspots[kHSToyUfo].x2 = _toyUfoX + 25; +			_hotspots[kHSToyUfo].y2 = _toyUfoY + 20; +		} +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 0, -1, -1, -1, -1); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		if (isFlag(12)) { + +			switch (_sceneClickedHotspot) { + +			case kHSUfoExitLeft: +				if (_toyUfoActionStatus < 0) { +					_isLeavingScene = 1; +					_toyUfoActionStatus = 7; +					_newSceneNum = 45; +					toyUfoFlyTo(-35, -1, -35, 799, 0, 300, 2); +				} +				break; +	 +			case kHSUfoExitRight: +				if (_toyUfoActionStatus < 0) { +					_isLeavingScene = 1; +					_toyUfoActionStatus = 7; +					_newSceneNum = 42; +					toyUfoFlyTo(835, -1, 0, 835, 0, 300, 2); +				} +				break; +	 +			case kHSUfoDevice: +				runMenu(); +				scene41_updateHotspots(); +				_timers[4] = getRandom(100) + 100; +				_timers[5] = getRandom(30) + 20; +				break; +		 +			} + +		} else { + +			switch (_sceneClickedHotspot) { +	 +			case kHSDevice: +				runMenu(); +				scene41_updateHotspots(); +				_timers[4] = getRandom(100) + 100; +				_timers[5] = getRandom(30) + 20; +				break; +	 +			case kHSPlatypus: +				if (_gnapActionStatus < 0) { +					if (_grabCursorSpriteIndex >= 0) { +						playGnapImpossible(_platX, _platY); +					} else { +						switch (_verbCursor) { +						case LOOK_CURSOR: +							playGnapMoan1(_platX, _platY); +							break; +						case GRAB_CURSOR: +							gnapKissPlatypus(0); +							break; +						case TALK_CURSOR: +							playGnapBrainPulsating(_platX, _platY); +							playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +							break; +						case PLAT_CURSOR: +							playGnapImpossible(_platX, _platY); +							break; +						} +					} +				} +				break; +	 +			case kHSExitCave: +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[kHSExitCave].x, _hotspotsWalkPos[kHSExitCave].y, 0, 0x107AE, 1); +				_gnapActionStatus = 0; +				_newSceneNum = 40; +				break; +	 +			case kHSExit: +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[kHSExit].x, -1, 0, 0x107AF, 1); +				_gnapActionStatus = 0; +				platypusWalkTo(_hotspotsWalkPos[kHSExit].x, -1, -1, 0x107CF, 1); +				_newSceneNum = 45; +				break; +	 +			case kHSExitBBQ: +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[kHSExitBBQ].x, -1, 0, 0x107AB, 1); +				_gnapActionStatus = 0; +				platypusWalkTo(_hotspotsWalkPos[kHSExitBBQ].x, -1, -1, 0x107CD, 1); +				_newSceneNum = 42; +				break; +	 +			case kHSToyVendor: +				if (_grabCursorSpriteIndex == kItemDiceQuarterHole) { +					_gnapActionStatus = 1; +					gnapWalkTo(4, 7, 0, 0x107BB, 9); +					playGnapShowItem(_grabCursorSpriteIndex, 5, 0); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(4, 7, 5, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan1(5, 0); +						break; +					case GRAB_CURSOR: +						playGnapImpossible(0, 0); +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(4, 7, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = 2; +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +				break; +	 +			case kHSKid: +				if (_grabCursorSpriteIndex == kItemChickenBucket) { +					gnapWalkTo(7, 7, 0, 0x107BB, 1); +					_gnapIdleFacing = 7; +					_gnapActionStatus = 4; +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(7, 7, 8, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(9, 0); +						break; +					case GRAB_CURSOR: +						gnapWalkTo(7, 7, 0, 0x107BB, 1); +						_gnapIdleFacing = 7; +						_gnapActionStatus = 5; +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(7, 7, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +				break; +	 +			case kHSToyUfo: +				if (_grabCursorSpriteIndex == kItemGum) { +					playGnapPullOutDevice(9, 0); +					_gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, 0); +					_gnapActionStatus = 3; +				} +				break; +	 +			case kHSWalkArea1: +				if (_gnapActionStatus < 0) +					gnapWalkTo(-1, -1, -1, -1, 1); +				break; +			} + +		} +	 +		if (isFlag(12)) { +			if (!_timers[9] && _gnapActionStatus < 0) { +				_gnapActionStatus = 6; +				if (_gnapSequenceId == 0x121 || _gnapSequenceId == 0x122) { +					_gameSys->insertSequence(0x123, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +					_gnapSequenceId = 0x123; +					_gnapSequenceDatNum = 0; +					_gameSys->setAnimation(0x123, _gnapId, 0); +				} +			} +		} +	 +		if (_mouseClickState.left && _gnapActionStatus < 0) { +			_mouseClickState.left = false; +			if (isFlag(12)) { +				int sequenceId; +				if (_leftClickMouseX >= 400) { +					if (_gnapSequenceId == 0x11F || _gnapSequenceId == 0x120 || _gnapSequenceId == 0x123 || _gnapSequenceId == 0x126) +						sequenceId = 0x120; +					else if (_leftClickMouseX - _toyUfoX >= 400) +						sequenceId = 0x126; +					else +						sequenceId = 0x123; +				} else { +					if (_gnapSequenceId == 0x121 || _gnapSequenceId == 0x125 || _gnapSequenceId == 0x122) +						sequenceId = 0x122; +					else if (_toyUfoX - _leftClickMouseX >= 400) +						sequenceId = 0x125; +					else +						sequenceId = 0x121; +				} +				_gameSys->insertSequence(sequenceId, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +				_gnapSequenceId = sequenceId; +				_gnapSequenceDatNum = 0; +				_gameSys->setAnimation(sequenceId, _gnapId, 0); +				_toyUfoActionStatus = 8; +				toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 2); +			} else { +				gnapWalkTo(-1, -1, -1, -1, 1); +			} +		} + +		scene41_updateAnimations(); +	 +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0) +				updateBeaverIdleSequence(); +			if (_gnapActionStatus < 0 && !isFlag(12)) +				updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = getRandom(100) + 100; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _toyUfoActionStatus == -1 && _s41_dword_47F2C8 == -1) { +					_gnapRandomValue = getRandom(3); +					switch (_gnapRandomValue) { +					case 0: +						_s41_dword_47F2C8 = 0x113; +						break; +					case 1: +						_s41_dword_47F2C8 = 0x117; +						break; +					case 2: +						_s41_dword_47F2C8 = 0x119; +						break; +					} +					if (_s41_dword_47F2C8 == _s41_dword_47F2CC) +						_s41_dword_47F2C8 = -1; +				} +			} +			if (!_timers[5]) { +				_timers[5] = getRandom(30) + 20; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _toyUfoActionStatus == -1 && _s41_dword_47F2C0 == -1) { +					if (isFlag(12)) +						_s41_dword_47F2C0 = 0x11B; +					else if (getRandom(3) != 0) +						_s41_dword_47F2C0 = 0x11D; +					else +						_s41_dword_47F2C0 = 0x11E; +				} +			} +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene41_updateHotspots(); +			_timers[4] = getRandom(100) + 100; +			_timers[5] = getRandom(30) + 20; +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene41_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		switch (_gnapActionStatus) { +		case 0: +			_gameSys->setAnimation(0, 0, 0); +			_sceneDone = true; +			_gnapActionStatus = -1; +			break; +		case 1: +			_gameSys->setAnimation(0, 0, 0); +			_s41_dword_47F2C8 = 0x114; +			_gnapActionStatus = -1; +			break; +		case 2: +			_gameSys->setAnimation(0, 0, 0); +			_s41_dword_47F2C8 = 0x116; +			_gnapActionStatus = -1; +			break; +		case 3: +			_gameSys->setAnimation(0, 0, 0); +			playGnapUseDevice(9, 0); +			_gnapActionStatus = -1; +			setGrabCursorSprite(-1); +			invRemove(kItemGum); +			_toyUfoActionStatus = 9; +			break; +		case 4: +			if (_gameSys->getAnimationStatus(4) == 2) { +				_timers[2] = getRandom(30) + 20; +				_timers[3] = getRandom(50) + 200; +				setGrabCursorSprite(-1); +				_gameSys->insertSequence(0x11F, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +				_gnapSequenceId = 0x11F; +				_gnapSequenceDatNum = 0; +				_gameSys->setAnimation(0x11F, _gnapId, 0); +				_s41_dword_47F2C0 = 0x11A; +				_gameSys->insertSequence(0x11A, 1, _s41_dword_47F2C4, 1, kSeqSyncWait, 0, 0, 0); +				_gameSys->setAnimation(_s41_dword_47F2C0, 1, 4); +				_s41_dword_47F2C4 = _s41_dword_47F2C0; +				_s41_dword_47F2C0 = 0x11B; +				_timers[5] = getRandom(30) + 20; +				_gnapActionStatus = -1; +				setFlag(12); +				scene41_updateHotspots(); +				_timers[9] = 600; +			} +			break; +		case 5: +			if (_gameSys->getAnimationStatus(3) == 2 && _gameSys->getAnimationStatus(4) == 2) { +				_timers[2] = getRandom(30) + 20; +				_timers[3] = getRandom(50) + 200; +				_gameSys->insertSequence(0x110, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +				_gnapSequenceId = 0x110; +				_gnapSequenceDatNum = 0; +				_gameSys->setAnimation(0x110, _gnapId, 0); +				_s41_dword_47F2C8 = 0x111; +				_gameSys->insertSequence(0x111, 1, _s41_dword_47F2CC, 1, kSeqSyncWait, 0, 0, 0); +				_gameSys->setAnimation(_s41_dword_47F2C8, 1, 3); +				_s41_dword_47F2CC = _s41_dword_47F2C8; +				_s41_dword_47F2C8 = -1; +				_timers[4] = getRandom(100) + 100; +				_s41_dword_47F2C0 = 0x10F; +				_gameSys->insertSequence(0x10F, 1, _s41_dword_47F2C4, 1, kSeqSyncWait, 0, 0, 0); +				_gameSys->setAnimation(_s41_dword_47F2C0, 1, 4); +				_s41_dword_47F2C4 = _s41_dword_47F2C0; +				_s41_dword_47F2C0 = -1; +				_timers[5] = getRandom(30) + 20; +				_gnapActionStatus = -1; +			} +			break; +		case 6: +			if (_gameSys->getAnimationStatus(3) == 2 && _gameSys->getAnimationStatus(4) == 2) { +				_timers[2] = getRandom(30) + 20; +				_timers[3] = getRandom(50) + 200; +				_gameSys->insertSequence(0x124, _gnapId, +					makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +					kSeqSyncWait, 0, 0, 0); +				_gnapSequenceId = 0x124; +				_gnapSequenceDatNum = 0; +				_gameSys->setAnimation(0x124, _gnapId, 0); +				_s41_dword_47F2C8 = 0x112; +				_gameSys->insertSequence(0x112, 1, _s41_dword_47F2CC, 1, kSeqSyncWait, 0, 0, 0); +				_gameSys->setAnimation(_s41_dword_47F2C8, 1, 3); +				_s41_dword_47F2CC = _s41_dword_47F2C8; +				_s41_dword_47F2C8 = -1; +				_timers[4] = getRandom(100) + 100; +				_s41_dword_47F2C0 = 0x11C; +				_gameSys->insertSequence(0x11C, 1, _s41_dword_47F2C4, 1, kSeqSyncWait, 0, 0, 0); +				_gameSys->setAnimation(_s41_dword_47F2C0, 1, 4); +				_s41_dword_47F2C4 = _s41_dword_47F2C0; +				_s41_dword_47F2C0 = -1; +				_timers[5] = getRandom(30) + 20; +				_gnapActionStatus = -1; +				clearFlag(12); +				scene41_updateHotspots(); +			} +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(2) == 2) { +		switch (_toyUfoActionStatus) { +		case 7: +			_sceneDone = true; +			break; +		case 9: +			_toyUfoNextSequenceId = 0x873; +			_gameSys->insertSequence(0x10873, _toyUfoId, _toyUfoSequenceId | 0x10000, _toyUfoId, +				kSeqSyncWait, 0, _toyUfoX - 365, _toyUfoY - 128); +			_toyUfoSequenceId = _toyUfoNextSequenceId; +			_gameSys->setAnimation(_toyUfoNextSequenceId | 0x10000, _toyUfoId, 2); +			toyUfoSetStatus(17); +			break; +		default: +			_toyUfoNextSequenceId = toyUfoGetSequenceId(); +			_gameSys->insertSequence(_toyUfoNextSequenceId | 0x10000, _toyUfoId + 1, _toyUfoSequenceId | 0x10000, _toyUfoId, +				kSeqSyncWait, 0, _toyUfoX - 274, _toyUfoY - 128); +			_toyUfoSequenceId = _toyUfoNextSequenceId; +			++_toyUfoId; +			_gameSys->setAnimation(_toyUfoNextSequenceId | 0x10000, _toyUfoId, 2); +			break; +		} +		_toyUfoActionStatus = -1; +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2 && _s41_dword_47F2C8 != -1) { +		_gameSys->insertSequence(_s41_dword_47F2C8, 1, _s41_dword_47F2CC, 1, kSeqSyncWait, 0, 0, 0); +		_gameSys->setAnimation(_s41_dword_47F2C8, 1, 3); +		_s41_dword_47F2CC = _s41_dword_47F2C8; +		_s41_dword_47F2C8 = -1; +		_timers[4] = getRandom(100) + 100; +	} +	 +	if (_gameSys->getAnimationStatus(4) == 2 && _s41_dword_47F2C0 != -1) { +		_gameSys->insertSequence(_s41_dword_47F2C0, 1, _s41_dword_47F2C4, 1, kSeqSyncWait, 0, 0, 0); +		_gameSys->setAnimation(_s41_dword_47F2C0, 1, 4); +		_s41_dword_47F2C4 = _s41_dword_47F2C0; +		_s41_dword_47F2C0 = -1; +		_timers[5] = getRandom(30) + 20; +		if (_s41_dword_47F2C4 == 0x11E) { +			_toyUfoActionStatus = 8; +			toyUfoFlyTo(getRandom(300) + 500, getRandom(225) + 75, 0, 799, 0, 300, 2); +		} +	} +   +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene42.cpp b/engines/gnap/scenes/scene42.cpp new file mode 100644 index 0000000000..2f98a820a2 --- /dev/null +++ b/engines/gnap/scenes/scene42.cpp @@ -0,0 +1,494 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSExitUfoParty	= 1, +	kHSExitToyStand	= 2, +	kHSExitUfo		= 3, +	kHSBBQVendor	= 4, +	kHSChickenLeg	= 5, +	kHSDevice		= 6, +	kHSWalkArea1	= 7, +	kHSWalkArea2	= 8 +}; + +enum { +	kHSUfoExitLeft	= 1, +	kHSUfoExitRight	= 2, +	kHSUfoHotSauce	= 3, +	kHSUfoDevice	= 4 +}; + +int GnapEngine::scene42_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	_gameSys->setAnimation(0, 0, 2); +	if (isFlag(20) || (isFlag(18) && isFlag(23))) +		return 0x153; +	return 0x152; +} + +void GnapEngine::scene42_updateHotspots() { +	if (isFlag(12)) { +		setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED); +		setHotspot(kHSUfoExitLeft, 0, 0, 10, 599, SF_EXIT_L_CURSOR); +		setHotspot(kHSUfoExitRight, 790, 0, 799, 599, SF_EXIT_R_CURSOR); +		setHotspot(kHSUfoHotSauce, 335, 110, 440, 175, SF_DISABLED); +		setDeviceHotspot(kHSUfoDevice, -1, 534, -1, 599); +		if ((isFlag(20) || isFlag(18)) && isFlag(23) && !isFlag(24)) +			_hotspots[kHSUfoHotSauce].flags = SF_GRAB_CURSOR; +		_hotspotsCount = 5; +	} else { +		setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +		setHotspot(kHSExitUfoParty, 150, 585, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9); +		setHotspot(kHSExitToyStand, 0, 100, 10, 599, SF_EXIT_L_CURSOR, 0, 8); +		setHotspot(kHSExitUfo, 790, 100, 799, 599, SF_EXIT_R_CURSOR, 10, 8); +		setHotspot(kHSBBQVendor, 410, 200, 520, 365, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 4, 8); +		setHotspot(kHSChickenLeg, 530, 340, 620, 430, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 8, 7); +		setHotspot(kHSWalkArea1, 0, 0, 800, 445); +		setHotspot(kHSWalkArea2, 240, 0, 550, 495); +		setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +		_hotspotsCount = 9; +	} +} + +void GnapEngine::scene42_run() { + +	queueInsertDeviceIcon(); + +	_s42_dword_47F2B8 = 0x14A; +	_s42_dword_47F2BC = -1; + +	_gameSys->setAnimation(0x14A, 1, 2); +	_gameSys->insertSequence(_s42_dword_47F2B8, 1, 0, 0, kSeqNone, 0, 0, 0); + +	if (isFlag(12)) { +		_toyUfoId = 0; +		_toyUfoActionStatus = -1; +		if (_prevSceneNum == 43 && isFlag(18)) { +			_toyUfoSequenceId = 0x872; +			_toyUfoNextSequenceId = toyUfoGetSequenceId(); +			_gameSys->insertSequence(_toyUfoSequenceId | 0x10000, _toyUfoId, 0, 0, kSeqNone, 0, 0, 0); +			_toyUfoX = 317; +			_toyUfoY = 61; +			toyUfoSetStatus(17); +			setFlag(20); +			_timers[9] = 600; +		} else { +			_toyUfoSequenceId = toyUfoGetSequenceId(); +			_toyUfoNextSequenceId = _toyUfoSequenceId; +			if (_prevSceneNum == 41) +				_toyUfoX = 30; +			else +				_toyUfoX = 770; +			_gameSys->insertSequence(_toyUfoSequenceId | 0x10000, _toyUfoId, 0, 0, kSeqNone, 0, _toyUfoX - 274, _toyUfoY - 128); +		} +		_gameSys->setAnimation(_toyUfoSequenceId | 0x10000, _toyUfoId, 3); +		endSceneInit(); +		if (_toyUfoSequenceId == 0x872) +			setGrabCursorSprite(-1); +	} else if (_prevSceneNum == 41) { +		initGnapPos(-1, 8, 7); +		initBeaverPos(-1, 9, 5); +		endSceneInit(); +		gnapWalkTo(2, 8, -1, 0x107B9, 1); +		platypusWalkTo(1, 8, -1, 0x107C2, 1); +	} else if (_prevSceneNum == 43) { +		initGnapPos(11, 8, 7); +		initBeaverPos(11, 9, 5); +		endSceneInit(); +		gnapWalkTo(8, 8, -1, 0x107BA, 1); +		platypusWalkTo(9, 8, -1, 0x107D2, 1); +	} else { +		initGnapPos(5, 11, 7); +		initBeaverPos(6, 11, 5); +		endSceneInit(); +		gnapWalkTo(5, 8, -1, 0x107BA, 1); +		platypusWalkTo(6, 8, -1, 0x107C2, 1); +	} + +	while (!_sceneDone) { +	 +		if (!isSoundPlaying(0x1094B)) +			playSound(0x1094B, 1); +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 0, -1, -1, -1, -1); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		if (isFlag(12)) { + +			switch (_sceneClickedHotspot) { + +			case kHSUfoExitLeft: +				if (_toyUfoActionStatus < 0) { +					_isLeavingScene = true; +					_toyUfoActionStatus = 5; +					_newSceneNum = 41; +					toyUfoFlyTo(-35, -1, -35, 799, 0, 300, 3); +				} +				break; + +			case kHSUfoExitRight: +				if (_toyUfoActionStatus < 0) { +					_isLeavingScene = true; +					_toyUfoActionStatus = 5; +					_newSceneNum = 43; +					toyUfoFlyTo(835, -1, 0, 835, 0, 300, 3); +				} +				break; + +			case kHSUfoHotSauce: +				if (isFlag(17)) { +					_toyUfoActionStatus = 7; +					toyUfoFlyTo(384, 77, 0, 799, 0, 300, 3); +					_timers[9] = 600; +				} else { +					_toyUfoActionStatus = 6; +					toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 3); +				} +				break; + +			case kHSUfoDevice: +				runMenu(); +				scene42_updateHotspots(); +				break; + +			} + +		} else { + +			switch (_sceneClickedHotspot) { + +			case kHSDevice: +				runMenu(); +				scene42_updateHotspots(); +				_timers[4] = getRandom(20) + 30; +				break; +			 +			case kHSPlatypus: +				if (_gnapActionStatus < 0) { +					if (_grabCursorSpriteIndex >= 0) { +						playGnapImpossible(_platX, _platY); +					} else { +						switch (_verbCursor) { +						case LOOK_CURSOR: +							playGnapMoan1(_platX, _platY); +							break; +						case GRAB_CURSOR: +							gnapKissPlatypus(0); +							break; +						case TALK_CURSOR: +							playGnapBrainPulsating(_platX, _platY); +							playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +							break; +						case PLAT_CURSOR: +							playGnapImpossible(_platX, _platY); +							break; +						} +					} +				} +				break; + +			case kHSExitUfoParty: +				_isLeavingScene = true; +				gnapWalkTo(_gnapX, _hotspotsWalkPos[kHSExitUfoParty].y, 0, 0x107AE, 1); +				_gnapActionStatus = 0; +				platypusWalkTo(_platX, _hotspotsWalkPos[kHSExitUfoParty].y, -1, 0x107C7, 1); +				_newSceneNum = 40; +				break; + +			case kHSExitToyStand: +				_isLeavingScene = true; +				gnapWalkTo(_hotspotsWalkPos[kHSExitToyStand].x, _gnapY, 0, 0x107AF, 1); +				_gnapActionStatus = 0; +				platypusWalkTo(_hotspotsWalkPos[kHSExitToyStand].x, _hotspotsWalkPos[kHSExitToyStand].y, -1, 0x107CF, 1); +				_newSceneNum = 41; +				break; + +			case kHSExitUfo: +				_isLeavingScene = true; +				gnapWalkTo(_hotspotsWalkPos[kHSExitUfo].x, _gnapY, 0, 0x107AB, 1); +				_gnapActionStatus = 0; +				platypusWalkTo(_hotspotsWalkPos[kHSExitUfo].x, _hotspotsWalkPos[kHSExitUfo].y, -1, 0x107CD, 1); +				_newSceneNum = 43; +				break; + +			case kHSBBQVendor: +				if (_grabCursorSpriteIndex == kItemDiceQuarterHole) { +					gnapWalkTo(_hotspotsWalkPos[kHSBBQVendor].x, _hotspotsWalkPos[kHSBBQVendor].y, 0, 0x107BB, 1); +					_gnapActionStatus = 2; +					if (_platY < 9) +						platypusWalkTo(_platX, 9, -1, -1, 1); +				} else if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSBBQVendor].x, _hotspotsWalkPos[kHSBBQVendor].y, _hotspotsWalkPos[kHSBBQVendor].x + 1, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(_hotspotsWalkPos[kHSBBQVendor].x - 1, 0); +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(_hotspotsWalkPos[kHSBBQVendor].x, _hotspotsWalkPos[kHSBBQVendor].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = 1; +						break; +					case GRAB_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +				break; +			 +			case kHSChickenLeg: +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSChickenLeg].x, _hotspotsWalkPos[kHSChickenLeg].y, _hotspotsWalkPos[kHSChickenLeg].x - 1, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(_hotspotsWalkPos[kHSChickenLeg].x - 1, 0); +						break; +					case GRAB_CURSOR: +						gnapWalkTo(_hotspotsWalkPos[kHSChickenLeg].x, _hotspotsWalkPos[kHSChickenLeg].y, 0, 0x107BC, 1); +						_gnapActionStatus = 4; +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +				break; +			 +			case kHSWalkArea1: +			case kHSWalkArea2: +				if (_gnapActionStatus < 0) +					gnapWalkTo(-1, -1, -1, -1, 1); +				break; +			 +			} +		 +		} +	 +		if (_mouseClickState.left && _gnapActionStatus < 0) { +			_mouseClickState.left = false; +			if (isFlag(12)) { +				_toyUfoActionStatus = 6; +				toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 3); +			} else { +				gnapWalkTo(-1, -1, -1, -1, 1); +			} +		} +	 +		scene42_updateAnimations(); +	 +		toyUfoCheckTimer(); +	 +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0 && !isFlag(12)) +				updateBeaverIdleSequence(); +			if (_gnapActionStatus < 0 && !isFlag(12)) +				updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = getRandom(20) + 30; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s42_dword_47F2BC == -1) { +					_gnapRandomValue = getRandom(8); +					switch (_gnapRandomValue) { +					case 0: +						_s42_dword_47F2BC = 0x14C; +						break; +					case 1: +					case 2: +						_s42_dword_47F2BC = 0x149; +						break; +					case 3: +					case 4: +					case 5: +					case 6: +						_s42_dword_47F2BC = 0x14D; +						break; +					case 7: +						_s42_dword_47F2BC = 0x14A; +						break; +					} +					if (_s42_dword_47F2BC == _s42_dword_47F2B8 && _s42_dword_47F2BC != 0x14D) +						_s42_dword_47F2BC = -1; +				} +			} +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene42_updateHotspots(); +			_timers[4] = getRandom(20) + 30; +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene42_updateAnimations() { +	int sequenceId; + +	if (_gameSys->getAnimationStatus(0) == 2) { +		switch (_gnapActionStatus) { +		case 0: +			_gameSys->setAnimation(0, 0, 0); +			_gnapActionStatus = -1; +			_sceneDone = true; +			break; +		case 1: +			_gameSys->setAnimation(0, 0, 0); +			_gnapActionStatus = -1; +			_s42_dword_47F2BC = 0x14B; +			break; +		case 3: +			_gameSys->setAnimation(0, 0, 0); +			setGrabCursorSprite(kItemChickenBucket); +			_gnapActionStatus = -1; +			break; +		case 2: +		case 4: +			if (_gameSys->getAnimationStatus(2) == 2) { +				if (_gnapActionStatus == 2) { +					invRemove(kItemDiceQuarterHole); +					invAdd(kItemChickenBucket); +					setGrabCursorSprite(-1); +					sequenceId = 0x150; +					_s42_dword_47F2BC = 0x148; +				} else if (isFlag(27)) { +					if (isFlag(28)) { +						sequenceId = 0x7B7; +						_s42_dword_47F2BC = 0x145; +					} else { +						setFlag(28); +						sequenceId = 0x14F; +						_s42_dword_47F2BC = 0x147; +					} +				} else { +					setFlag(27); +					sequenceId = 0x14E; +					_s42_dword_47F2BC = 0x146; +				} +				if (sequenceId == 0x7B7) { +					_gameSys->insertSequence(0x107B7, _gnapId, +						makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +						kSeqSyncWait, getSequenceTotalDuration(_s42_dword_47F2BC), +						75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +					_gnapSequenceDatNum = 1; +				} else { +					_gameSys->insertSequence(sequenceId, _gnapId, +						makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +						kSeqSyncWait, 0, 0, 0); +					_gnapSequenceDatNum = 0; +				} +				_gnapSequenceId = sequenceId; +				_gameSys->setAnimation(sequenceId | (_gnapSequenceDatNum << 16), _gnapId, 0); +				if (_gnapActionStatus == 2) +					_gnapActionStatus = 3; +				else +					_gnapActionStatus = -1; +				_gameSys->insertSequence(_s42_dword_47F2BC, 1, _s42_dword_47F2B8, 1, kSeqSyncWait, 0, 0, 0); +				_gameSys->setAnimation(_s42_dword_47F2BC, 1, 2); +				_s42_dword_47F2B8 = _s42_dword_47F2BC; +				if (_s42_dword_47F2BC == 0x145) +					_s42_dword_47F2BC = 0x14A; +				else +					_s42_dword_47F2BC = -1; +				_timers[4] = getRandom(20) + 30; +				_timers[2] = getRandom(30) + 20; +				_timers[3] = getRandom(50) + 200; +			} +			break; +		default: +			_gameSys->setAnimation(0, 0, 0); +			_gnapActionStatus = -1; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(2) == 2 && _s42_dword_47F2BC != -1) { +		_gameSys->insertSequence(_s42_dword_47F2BC, 1, _s42_dword_47F2B8, 1, kSeqSyncWait, 0, 0, 0); +		_gameSys->setAnimation(_s42_dword_47F2BC, 1, 2); +		_s42_dword_47F2B8 = _s42_dword_47F2BC; +		_s42_dword_47F2BC = -1; +		_timers[4] = getRandom(20) + 30; +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2) { +		switch (_toyUfoActionStatus) { +		case 5: +			_sceneDone = true; +			break; +		case 7: +			_gameSys->insertSequence(0x10870, _toyUfoId, _toyUfoSequenceId | 0x10000, _toyUfoId, kSeqSyncWait, 0, 0, 0); +			setFlag(24); +			scene42_updateHotspots(); +			toyUfoSetStatus(19); +			_toyUfoSequenceId = 0x870; +			_gameSys->setAnimation(0x10870, _toyUfoId, 3); +			_toyUfoActionStatus = -1; +			_toyUfoX = 0x181; +			_toyUfoY = 53; +			break; +		default: +			if (_toyUfoSequenceId == 0x872) { +				hideCursor(); +				addFullScreenSprite(0x13E, 255); +				_gameSys->setAnimation(0x151, 256, 0); +				_gameSys->insertSequence(0x151, 256, 0, 0, kSeqNone, 0, 0, 0); +				while (_gameSys->getAnimationStatus(0) != 2) +					gameUpdateTick(); +				removeFullScreenSprite(); +				showCursor(); +			} +			_toyUfoNextSequenceId = toyUfoGetSequenceId(); +			_gameSys->setAnimation(_toyUfoNextSequenceId | 0x10000, (_toyUfoId + 1) % 10, 3); +			_gameSys->insertSequence(_toyUfoNextSequenceId | 0x10000, (_toyUfoId + 1) % 10, +				_toyUfoSequenceId | 0x10000, _toyUfoId, +				kSeqSyncWait, 0, _toyUfoX - 274, _toyUfoY - 128); +			_toyUfoSequenceId = _toyUfoNextSequenceId; +			_toyUfoId = (_toyUfoId + 1) % 10; +			break; +		} +		_toyUfoActionStatus = -1; +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene43.cpp b/engines/gnap/scenes/scene43.cpp new file mode 100644 index 0000000000..3510cb4d99 --- /dev/null +++ b/engines/gnap/scenes/scene43.cpp @@ -0,0 +1,484 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus			= 0, +	kHSDevice			= 1, +	kHSExitUfoParty		= 2, +	kHSExitBBQ			= 3, +	kHSExitKissinBooth	= 4, +	kHSTwoHeadedGuy		= 5, +	kHSKey				= 6, +	kHSUfo				= 7, +	kHSWalkArea1		= 8, +	kHSWalkArea2		= 9 +}; + +enum { +	kHSUfoExitLeft	= 1, +	kHSUfoExitRight	= 2, +	kHSUfoKey		= 3, +	kHSUfoBucket	= 4, +	kHSUfoDevice	= 5 +}; + +int GnapEngine::scene43_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	_gameSys->setAnimation(0, 0, 2); +	return 0x13F; +} + +void GnapEngine::scene43_updateHotspots() { +	if (isFlag(12)) { +		setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED); +		setHotspot(kHSUfoExitLeft, 0, 0, 10, 599, SF_EXIT_L_CURSOR); +		setHotspot(kHSUfoExitRight, 790, 0, 799, 599, SF_EXIT_R_CURSOR); +		setHotspot(kHSUfoKey, 140, 170, 185, 260, SF_GRAB_CURSOR); +		setHotspot(kHSUfoBucket, 475, 290, 545, 365, SF_DISABLED); +		setDeviceHotspot(kHSUfoDevice, -1, 534, -1, 599); +		if (isFlag(19)) +			_hotspots[kHSUfoBucket].flags = SF_GRAB_CURSOR; +		// NOTE Bug in the original. Key hotspot wasn't disabled. +		if (isFlag(14)) +			_hotspots[kHSUfoKey].flags = SF_DISABLED; +		_hotspotsCount = 6; +	} else { +		setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +		setHotspot(kHSExitUfoParty, 150, 580, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9); +		setHotspot(kHSExitBBQ, 0, 100, 10, 599, SF_EXIT_L_CURSOR, 0, 8); +		setHotspot(kHSExitKissinBooth, 790, 100, 799, 599, SF_EXIT_R_CURSOR, 10, 8); +		setHotspot(kHSTwoHeadedGuy, 470, 240, 700, 470, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +		setHotspot(kHSKey, 140, 170, 185, 260, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +		setHotspot(kHSUfo, 110, 0, 690, 350, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +		setHotspot(kHSWalkArea1, 0, 0, 800, 445); +		setHotspot(kHSWalkArea2, 465, 0, 800, 493); +		setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +        if (isFlag(14)) +			_hotspots[kHSKey].flags = SF_DISABLED; +		_hotspotsCount = 10; +	} +} + +void GnapEngine::scene43_run() { + +	queueInsertDeviceIcon(); + +	if (!isFlag(14)) +		_gameSys->insertSequence(0x1086F, 1, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s43_dword_47F2B0 = 0x13C; +	_s43_dword_47F2B4 = -1; +	 +	_gameSys->setAnimation(0x13C, 1, 2); +	_gameSys->insertSequence(_s43_dword_47F2B0, 1, 0, 0, kSeqNone, 0, 0, 0); +	 +	if (isFlag(12)) { +		_toyUfoId = 0; +		_toyUfoActionStatus = -1; +		_toyUfoSequenceId = toyUfoGetSequenceId(); +		_toyUfoNextSequenceId = _toyUfoSequenceId; +		if (_prevSceneNum == 42) +			_toyUfoX = 30; +		else +			_toyUfoX = 770; +		_gameSys->setAnimation(_toyUfoSequenceId | 0x10000, _toyUfoId, 3); +		_gameSys->insertSequence(_toyUfoSequenceId | 0x10000, _toyUfoId, 0, 0, kSeqNone, 0, _toyUfoX - 274, _toyUfoY - 128); +		endSceneInit(); +	} else { +		switch (_prevSceneNum) { +		case 42: +			initGnapPos(-1, 8, 7); +			initBeaverPos(-1, 9, 5); +			endSceneInit(); +			gnapWalkTo(2, 8, -1, 0x107B9, 1); +			platypusWalkTo(1, 8, -1, 0x107C2, 1); +			break; +		case 44: +			initGnapPos(11, 8, 7); +			initBeaverPos(11, 9, 5); +			endSceneInit(); +			gnapWalkTo(8, 8, -1, 0x107BA, 1); +			platypusWalkTo(9, 8, -1, 0x107D2, 1); +			break; +		case 54: +			initGnapPos(4, 7, 3); +			initBeaverPos(11, 8, 5); +			endSceneInit(); +			platypusWalkTo(9, 8, -1, 0x107D2, 1); +			break; +		default: +			initGnapPos(5, 11, 7); +			initBeaverPos(6, 11, 5); +			endSceneInit(); +			gnapWalkTo(5, 8, -1, 0x107BA, 1); +			platypusWalkTo(6, 8, -1, 0x107C2, 1); +			break; +		} +	} +	 +	while (!_sceneDone) { +	 +		if (!isSoundPlaying(0x1094B)) +			playSound(0x1094B, 1); +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 0, -1, -1, -1, -1); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		if (isFlag(12)) { + +			switch (_sceneClickedHotspot) { + +			case kHSUfoDevice: +				runMenu(); +				scene43_updateHotspots(); +				_timers[4] = getRandom(100) + 100; +				break; +			 +			case kHSUfoExitLeft: +				if (_toyUfoActionStatus < 0) { +					_isLeavingScene = 1; +					_toyUfoActionStatus = 4; +					_newSceneNum = 42; +					toyUfoFlyTo(-35, -1, -35, 799, 0, 300, 3); +				} +				break; +			 +			case kHSUfoExitRight: +				if (_toyUfoActionStatus < 0) { +					_isLeavingScene = 1; +					_toyUfoActionStatus = 4; +					_newSceneNum = 44; +					toyUfoFlyTo(835, -1, 0, 835, 0, 300, 3); +				} +				break; +			 +			case kHSUfoKey: +				if (isFlag(17)) { +					_toyUfoActionStatus = 6; +					toyUfoFlyTo(163, 145, 0, 799, 0, 300, 3); +				} else { +					_toyUfoActionStatus = 5; +					toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 3); +				} +				break; +			 +			case kHSUfoBucket: +				_toyUfoActionStatus = 7; +				toyUfoFlyTo(497, 143, 0, 799, 0, 300, 3); +				_timers[9] = 600; +				break; +			} + +		} else { + +			switch (_sceneClickedHotspot) { + +			case kHSDevice: +				runMenu(); +				scene43_updateHotspots(); +				_timers[4] = getRandom(100) + 100; +				break; + +			case kHSPlatypus: +				if (_gnapActionStatus < 0) { +					if (_grabCursorSpriteIndex >= 0) { +						playGnapImpossible(_platX, _platY); +					} else { +						switch (_verbCursor) { +						case LOOK_CURSOR: +							playGnapMoan1(_platX, _platY); +							break; +						case GRAB_CURSOR: +							gnapKissPlatypus(0); +							break; +						case TALK_CURSOR: +							playGnapBrainPulsating(_platX, _platY); +							playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +							break; +						case PLAT_CURSOR: +							playGnapImpossible(_platX, _platY); +							break; +						} +					} +				} +				break; + +			case kHSExitUfoParty: +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[kHSExitUfoParty].x, _hotspotsWalkPos[kHSExitUfoParty].y, 0, 0x107AE, 1); +				_gnapActionStatus = 0; +				platypusWalkTo(_hotspotsWalkPos[kHSExitUfoParty].x, _hotspotsWalkPos[kHSExitUfoParty].y, -1, 0x107C7, 1); +				_newSceneNum = 40; +				break; + +			case kHSExitBBQ: +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[kHSExitBBQ].x, _gnapY, 0, 0x107AF, 1); +				_gnapActionStatus = 0; +				platypusWalkTo(_hotspotsWalkPos[kHSExitBBQ].x, _hotspotsWalkPos[kHSExitBBQ].y, -1, 0x107CF, 1); +				_newSceneNum = 42; +				break; + +			case kHSExitKissinBooth: +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[kHSExitKissinBooth].x, _gnapY, 0, 0x107AB, 1); +				_gnapActionStatus = 0; +				platypusWalkTo(_hotspotsWalkPos[kHSExitKissinBooth].x, _hotspotsWalkPos[kHSExitKissinBooth].y, -1, 0x107CD, 1); +				_newSceneNum = 44; +				break; + +			case kHSTwoHeadedGuy: +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(6, 8, 7, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(7, 0); +						break; +					case TALK_CURSOR: +							_gnapIdleFacing = 7; +							gnapWalkTo(5, 8, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +							_gnapActionStatus = 2; +						break; +					case GRAB_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +				break; + +			case kHSKey: +			case kHSUfo: +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(3, 7, 2, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(0, 0); +						break; +					case GRAB_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(3, 7, 0, 67515, 1); +						_gnapActionStatus = 1; +						break; +					case TALK_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +				break; + +			case kHSWalkArea1: +			case kHSWalkArea2: +				if (_gnapActionStatus < 0) +					gnapWalkTo(-1, -1, -1, -1, 1); +				break; + +			} + +		} +	 +		if (_mouseClickState.left && _gnapActionStatus < 0) { +			_mouseClickState.left = false; +			if (isFlag(12) && (_toyUfoActionStatus == 5 || _toyUfoActionStatus == -1)) { +				_toyUfoActionStatus = 5; +				toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 3); +			} else { +				gnapWalkTo(-1, -1, -1, -1, 1); +			} +		} +	 +		scene43_updateAnimations(); +	 +		toyUfoCheckTimer(); +	 +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0 && !isFlag(12)) +				updateBeaverIdleSequence(); +			if (_gnapActionStatus < 0 && !isFlag(12)) +				updateGnapIdleSequence(); +			if (!_timers[4] && (!isFlag(12) || !isFlag(19))) { +				_timers[4] = getRandom(100) + 100; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s43_dword_47F2B4 == -1) { +					_gnapRandomValue = getRandom(5); +					switch (_gnapRandomValue) { +					case 0: +						_s43_dword_47F2B4 = 0x13C; +						break; +					case 1: +						_s43_dword_47F2B4 = 0x134; +						break; +					case 2: +						_s43_dword_47F2B4 = 0x135; +						break; +					case 3: +						_s43_dword_47F2B4 = 0x136; +						break; +					case 4: +						_s43_dword_47F2B4 = 0x13A; +						break; +					} +					if (_s43_dword_47F2B4 == _s43_dword_47F2B0) +						_s43_dword_47F2B4 = -1; +				} +			} +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene43_updateHotspots(); +			_timers[4] = getRandom(100) + 100; +		} +		 +		gameUpdateTick(); +	 +	} +	 +	if (_newSceneNum == 54) +		clearFlag(12); + +} + +void GnapEngine::scene43_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		switch (_gnapActionStatus) { +		case 0: +			_gameSys->setAnimation(0, 0, 0); +			_sceneDone = true; +			break; +		case 1: +			if (_gameSys->getAnimationStatus(2) == 2) { +				_timers[2] = getRandom(30) + 20; +				_timers[3] = getRandom(50) + 200; +				_gameSys->insertSequence(0x13D, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +				_gnapSequenceId = 0x13D; +				_gnapSequenceDatNum = 0; +				_gameSys->setAnimation(0x13D, _gnapId, 0); +				_s43_dword_47F2B4 = 0x13B; +				_gameSys->insertSequence(0x13B, 1, _s43_dword_47F2B0, 1, kSeqSyncWait, 0, 0, 0); +				_gameSys->setAnimation(_s43_dword_47F2B4, 1, 2); +				_s43_dword_47F2B0 = _s43_dword_47F2B4; +				_s43_dword_47F2B4 = -1; +				_timers[4] = getRandom(100) + 100; +				_gnapActionStatus = -1; +			} +			break; +		default: +			_gameSys->setAnimation(0, 0, 0); +			_gnapActionStatus = -1; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(2) == 2) { +		if (_s43_dword_47F2B0 == 0x13A) { +			if (isFlag(19)) { +				_s43_dword_47F2B4 = 0x13E; +				stopSound(0x108F6); +			} else if (getRandom(2) != 0) { +				_s43_dword_47F2B4 = 0x137; +			} else { +				_s43_dword_47F2B4 = 0x138; +			} +		} else if (_s43_dword_47F2B0 == 0x13E) { +			_sceneDone = true; +			_newSceneNum = 54; +		} +		if (_s43_dword_47F2B4 != -1) { +			_gameSys->insertSequence(_s43_dword_47F2B4, 1, _s43_dword_47F2B0, 1, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s43_dword_47F2B4, 1, 2); +			_s43_dword_47F2B0 = _s43_dword_47F2B4; +			_s43_dword_47F2B4 = -1; +			_timers[4] = getRandom(100) + 100; +		} +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2) { +		switch (_toyUfoActionStatus) { +		case 4: +			_sceneDone = true; +			_toyUfoActionStatus = -1; +			break; +		case 6: +			_gameSys->insertSequence(0x10871, _toyUfoId, _toyUfoSequenceId | 0x10000, _toyUfoId, kSeqSyncWait, 0, 0, 0); +			_gameSys->removeSequence(0x1086F, 1, 1); +			setFlag(14); +			scene43_updateHotspots(); +			toyUfoSetStatus(18); +			_toyUfoSequenceId = 0x871; +			_gameSys->setAnimation(0x10871, _toyUfoId, 3); +			_toyUfoActionStatus = -1; +			_toyUfoX = 96; +			_toyUfoY = 131; +			break; +		case 7: +			_gameSys->insertSequence(0x10874, _toyUfoId, _toyUfoSequenceId | 0x10000, _toyUfoId, kSeqSyncWait, 0, 0, 0); +			_toyUfoSequenceId = 0x874; +			_gameSys->setAnimation(0x10874, _toyUfoId, 3); +			_toyUfoActionStatus = 8; +			setFlag(17); +			_gnapActionStatus = 3; +			break; +		case 8: +			_s43_dword_47F2B4 = 0x13A; +			_toyUfoX = 514; +			_toyUfoY = 125; +			toyUfoFlyTo(835, 125, 0, 835, 0, 300, 3); +			_toyUfoActionStatus = 9; +			break; +		case 9: +			// Nothing +			break; +		default: +			_toyUfoNextSequenceId = toyUfoGetSequenceId(); +			_gameSys->insertSequence(_toyUfoNextSequenceId | 0x10000, _toyUfoId + 1, +				_toyUfoSequenceId | 0x10000, _toyUfoId, +				kSeqSyncWait, 0, _toyUfoX - 274, _toyUfoY - 128); +			_toyUfoSequenceId = _toyUfoNextSequenceId; +			++_toyUfoId; +			_gameSys->setAnimation(_toyUfoNextSequenceId | 0x10000, _toyUfoId, 3); +			_toyUfoActionStatus = -1; +			break; +		} +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene44.cpp b/engines/gnap/scenes/scene44.cpp new file mode 100644 index 0000000000..b2c711898c --- /dev/null +++ b/engines/gnap/scenes/scene44.cpp @@ -0,0 +1,529 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus		= 0, +	kHSExitUfoParty	= 1, +	kHSExitUfo		= 2, +	kHSExitShow		= 3, +	kHSKissingLady	= 4, +	kHSSpring		= 5, +	kHSSpringGuy	= 6, +	kHSDevice		= 7, +	kHSWalkArea1	= 8, +	kHSWalkArea2	= 9 +}; + +enum { +	kHSUfoExitLeft	= 1, +	kHSUfoExitRight	= 2, +	kHSUfoDevice	= 3 +}; + +int GnapEngine::scene44_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	_gameSys->setAnimation(0, 0, 2); +	_gameSys->setAnimation(0, 0, 3); +	return 0xFF; +} + +void GnapEngine::scene44_updateHotspots() { +	if (isFlag(12)) { +		setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED); +		setHotspot(kHSUfoExitLeft, 0, 0, 10, 599, SF_EXIT_L_CURSOR); +		setHotspot(kHSUfoExitRight, 790, 0, 799, 599, SF_EXIT_R_CURSOR); +		setDeviceHotspot(kHSUfoDevice, -1, 534, -1, 599); +		_hotspotsCount = 4; +	} else { +		setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +		setHotspot(kHSExitUfoParty, 150, 580, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9); +		setHotspot(kHSExitUfo, 0, 100, 10, 599, SF_EXIT_L_CURSOR, 0, 8); +		setHotspot(kHSExitShow, 790, 100, 799, 599, SF_EXIT_R_CURSOR, 10, 8); +		setHotspot(kHSKissingLady, 300, 160, 400, 315, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 5, 7); +		setHotspot(kHSSpring, 580, 310, 635, 375, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 8); +		setHotspot(kHSSpringGuy, 610, 375, 690, 515, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 7, 8); +		setHotspot(kHSWalkArea1, 0, 0, 800, 445); +		setHotspot(kHSWalkArea2, 617, 0, 800, 600); +		setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +		if (isFlag(13)) +			_hotspots[kHSKissingLady].flags = SF_DISABLED; +		if (isFlag(15)) +			_hotspots[kHSSpring].flags = SF_DISABLED; +		_hotspotsCount = 10; +	} +} + +void GnapEngine::scene44_run() { + +	queueInsertDeviceIcon(); + +	_gameSys->insertSequence(0xF7, 0, 0, 0, kSeqLoop, 0, 0, 0); +	_gameSys->insertSequence(0xFC, 256, 0, 0, kSeqNone, 0, 0, 0); + +	if (isFlag(15)) +		_s44_dword_47EB0C = 0xF8; +	else +		_s44_dword_47EB0C = 0xF9; +	 +	_s44_dword_47EB04 = -1; +	_gameSys->setAnimation(_s44_dword_47EB0C, 1, 4); +	_gameSys->insertSequence(_s44_dword_47EB0C, 1, 0, 0, kSeqNone, 0, 0, 0); + +	if (isFlag(13)) { +		if (_prevSceneNum != 50 || _sceneSavegameLoaded) { +			_s44_dword_47EB10 = 0xF6; +			_s44_dword_47EB08 = -1; +		} else { +			setGrabCursorSprite(kItemGum); +			_s44_dword_47EB10 = 0xF5; +			_s44_dword_47EB08 = 0xF6; +			_gameSys->setAnimation(0xF5, 1, 2); +		} +	} else { +		_s44_dword_47EB10 = 0xEC; +		_s44_dword_47EB08 = -1; +		_gameSys->setAnimation(0xEC, 1, 2); +	} +	 +	_gameSys->insertSequence(_s44_dword_47EB10, 1, 0, 0, kSeqNone, 0, 0, 0); +	 +	if (isFlag(12)) { +		_toyUfoId = 0; +		_toyUfoActionStatus = -1; +		_toyUfoSequenceId = toyUfoGetSequenceId(); +		_toyUfoNextSequenceId = _toyUfoSequenceId; +		if (_prevSceneNum == 43) +			_toyUfoX = 30; +		else +			_toyUfoX = 770; +		_gameSys->setAnimation(_toyUfoSequenceId | 0x10000, _toyUfoId, 3); +		_gameSys->insertSequence(_toyUfoSequenceId | 0x10000, _toyUfoId, 0, 0, kSeqNone, 0, _toyUfoX - 274, _toyUfoY - 128); +		endSceneInit(); +	} else { +		switch (_prevSceneNum) { +		case 43: +			initGnapPos(-1, 8, 7); +			initBeaverPos(-1, 7, 5); +			endSceneInit(); +			gnapWalkTo(2, 8, -1, 0x107B9, 1); +			platypusWalkTo(1, 8, -1, 0x107C2, 1); +			break; +		case 46: +			initGnapPos(11, 8, 7); +			initBeaverPos(11, 8, 5); +			endSceneInit(); +			gnapWalkTo(6, 8, -1, 0x107BA, 1); +			platypusWalkTo(7, 8, -1, 0x107D2, 1); +			break; +		case 50: +			initGnapPos(4, 8, 1); +			if (_sceneSavegameLoaded) { +				initBeaverPos(_hotspotsWalkPos[4].x, _hotspotsWalkPos[4].y, 4); +			} else if (!isFlag(13)) { +				_timers[0] = 50; +				_timers[1] = 20; +				_platX = 5; +				_platY = 8; +				_beaverSequenceId = 0xFD; +				_beaverFacing = 0; +				_beaverId = 160; +				_beaverSequenceDatNum = 0; +				_gameSys->insertSequence(0xFD, 160, 0, 0, kSeqNone, 0, 0, 0); +			} +			endSceneInit(); +			break; +		default: +			initGnapPos(5, 11, 7); +			initBeaverPos(6, 11, 5); +			endSceneInit(); +			platypusWalkTo(6, 8, -1, 0x107C2, 1); +			gnapWalkTo(5, 8, -1, 0x107BA, 1); +			break; +		} +	} +	 +	while (!_sceneDone) { +	 +		if (!isSoundPlaying(0x1094B)) +			playSound(0x1094B, 1); +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 0, -1, -1, -1, -1); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		if (isFlag(12)) { + +			switch (_sceneClickedHotspot) { + +			case kHSUfoExitLeft: +				if (_toyUfoActionStatus < 0) { +					_isLeavingScene = 1; +					_toyUfoActionStatus = 6; +					_newSceneNum = 43; +					toyUfoFlyTo(-35, -1, -35, 799, 0, 300, 3); +				} +				break; + +			case kHSUfoExitRight: +				if (_toyUfoActionStatus < 0) { +					_isLeavingScene = 1; +					_toyUfoActionStatus = 6; +					_newSceneNum = 46; +					toyUfoFlyTo(835, -1, 0, 835, 0, 300, 3); +				} +				break; + +			case kHSUfoDevice: +				runMenu(); +				scene44_updateHotspots(); +				_timers[4] = getRandom(20) + 20; +				break; + +			} + +		} else if (_sceneClickedHotspot <= 9) { + +			switch (_sceneClickedHotspot) { + +			case kHSDevice: +				runMenu(); +				scene44_updateHotspots(); +				_timers[4] = getRandom(20) + 20; +				break; +			 +			case kHSPlatypus: +				if (_gnapActionStatus < 0) { +					if (_grabCursorSpriteIndex >= 0) { +						playGnapImpossible(_platX, _platY); +					} else { +						switch (_verbCursor) { +						case LOOK_CURSOR: +							playGnapMoan1(_platX, _platY); +							break; +						case GRAB_CURSOR: +							gnapKissPlatypus(0); +							break; +						case TALK_CURSOR: +							playGnapBrainPulsating(_platX, _platY); +							playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +							break; +						case PLAT_CURSOR: +							playGnapImpossible(_platX, _platY); +							break; +						} +					} +				} +				break; + +			case kHSExitUfoParty: +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[kHSExitUfoParty].x, _hotspotsWalkPos[kHSExitUfoParty].y, 0, 0x107AE, 1); +				_gnapActionStatus = 0; +				_newSceneNum = 40; +				break; +			 +			case kHSExitUfo: +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[kHSExitUfo].x, _gnapY, 0, 0x107AF, 1); +				_gnapActionStatus = 0; +				platypusWalkTo(_hotspotsWalkPos[kHSExitUfo].x, _platY, -1, 0x107CF, 1); +				_newSceneNum = 43; +				break; +			 +			case kHSExitShow: +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[kHSExitShow].x, _hotspotsWalkPos[kHSExitShow].y, 0, 0x107AB, 1); +				_gnapActionStatus = 0; +				_newSceneNum = 46; +				break; +			 +			case kHSKissingLady: +				if (_grabCursorSpriteIndex >= 0) { +					_gnapActionStatus = 2; +					gnapWalkTo(_hotspotsWalkPos[kHSKissingLady].x, _hotspotsWalkPos[kHSKissingLady].y, 0, -1, 9); +					playGnapShowItem(_grabCursorSpriteIndex, _hotspotsWalkPos[kHSKissingLady].x - 1, _hotspotsWalkPos[kHSKissingLady].y); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(4, 3); +						break; +					case GRAB_CURSOR: +						playGnapImpossible(0, 0); +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 5; +						gnapWalkTo(_hotspotsWalkPos[kHSKissingLady].x, _hotspotsWalkPos[kHSKissingLady].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = 1; +						break; +					case PLAT_CURSOR: +						gnapUseDeviceOnBeaver(); +						platypusWalkTo(6, 7, 1, 0x107D2, 1); +						if (_gnapX == 7 && _gnapY == 7) +							gnapWalkStep(); +						playGnapIdle(5, 7); +						_beaverActionStatus = 4; +						break; +					} +				} +				break; +			 +			case kHSSpring: +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSSpring].x, _hotspotsWalkPos[kHSSpring].y, 8, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapScratchingHead(8, 7); +						break; +					case GRAB_CURSOR: +						playGnapPullOutDevice(8, 0); +						playGnapUseDevice(8, 0); +						_s44_dword_47EB04 = 0xFB; +						invAdd(kItemSpring); +						setFlag(15); +						scene44_updateHotspots(); +						break; +					case TALK_CURSOR: +						playGnapImpossible(0, 0); +						break; +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +				break; +			 +			case kHSSpringGuy: +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSSpringGuy].x, _hotspotsWalkPos[kHSSpringGuy].y, 8, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						if (isFlag(15)) +							playGnapMoan1(8, 7); +						else +							playGnapScratchingHead(8, 7); +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(_hotspotsWalkPos[kHSSpringGuy].x, _hotspotsWalkPos[kHSSpringGuy].y, -1, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						break; +					case GRAB_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +				break; +			 +			case kHSWalkArea1: +			case kHSWalkArea2: +				if (_gnapActionStatus < 0) +					gnapWalkTo(-1, -1, -1, -1, 1); +				break; +			 +			} + +		} +	 +		if (_mouseClickState.left && _gnapActionStatus < 0) { +			_mouseClickState.left = false; +			if (isFlag(12)) { +				_toyUfoActionStatus = 7; +				toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 3); +			} else { +				gnapWalkTo(-1, -1, -1, -1, 1); +			} +		} +	 +		scene44_updateAnimations(); +	 +		toyUfoCheckTimer(); +	 +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0 && !isFlag(12) && _s44_dword_47EB10 != 0xF5) +				updateBeaverIdleSequence(); +			if (_gnapActionStatus < 0 && !isFlag(12)) +				updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = getRandom(20) + 20; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s44_dword_47EB08 == -1) { +					_gnapRandomValue = getRandom(20); +					switch (_gnapRandomValue) { +					case 0: +						_s44_dword_47EB08 = 0xED; +						break; +					case 1: +						_s44_dword_47EB08 = 0xEE; +						break; +					case 2: +						_s44_dword_47EB08 = 0xF0; +						break; +					case 3: +						_s44_dword_47EB08 = 0xF3; +						break; +					case 4: +						_s44_dword_47EB08 = 0xF4; +						break; +					default: +						_s44_dword_47EB08 = 0xEC; +						break; +					} +					if (_s44_dword_47EB08 != 0xEC && _s44_dword_47EB08 == _s44_dword_47EB10) +						_s44_dword_47EB08 = -1; +				} +			} +			if (!_timers[5]) { +				_timers[5] = getRandom(20) + 20; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s44_dword_47EB04 == -1) { +					_gnapRandomValue = getRandom(5); +					if (_gnapRandomValue != 0) { +						if (!isFlag(15)) +							_s44_dword_47EB04 = 0xF9; +					} else { +						if (isFlag(15)) +							_s44_dword_47EB04 = 0xF8; +						else +							_s44_dword_47EB04 = 0xFA; +					} +				} +			} +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene44_updateHotspots(); +			_timers[4] = getRandom(20) + 20; +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene44_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) 	{ +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case 0: +			_sceneDone = true; +			break; +		case 1: +			_s44_dword_47EB08 = 0xEF; +			break; +		case 2: +			_s44_dword_47EB08 = 0xF2; +			break; +		} +		_gnapActionStatus = -1; +	} +	 +	if (_gameSys->getAnimationStatus(1) == 2) { +		_gameSys->setAnimation(0, 0, 1); +		switch (_beaverActionStatus) { +		case 4: +			if (_gameSys->getAnimationStatus(2) == 2) { +				_gameSys->insertSequence(0xFE, _beaverId, _beaverSequenceId | (_beaverSequenceDatNum << 16), _beaverId, kSeqSyncWait, 0, 0, 0); +				_beaverSequenceId = 0xFE; +				_beaverSequenceDatNum = 0; +				_gameSys->setAnimation(0xFE, _beaverId, 1); +				_gameSys->removeSequence(_s44_dword_47EB10, 1, 1); +				_beaverActionStatus = 5; +			} +			break; +		case 5: +			_sceneDone = true; +			_newSceneNum = 50; +			break; +		default: +			_beaverActionStatus = -1; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(2) == 2) { +		if (_s44_dword_47EB08 == 0xF6) { +			_gameSys->insertSequence(_s44_dword_47EB08, 1, _s44_dword_47EB10, 1, kSeqSyncWait, 0, 0, 0); +			initBeaverPos(5, 8, 0); +			_s44_dword_47EB10 = _s44_dword_47EB08; +			_s44_dword_47EB08 = -1; +			_gameSys->setAnimation(0, 0, 2); +		} else if (_s44_dword_47EB08 != -1) { +			_gameSys->insertSequence(_s44_dword_47EB08, 1, _s44_dword_47EB10, 1, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s44_dword_47EB08, 1, 2); +			_s44_dword_47EB10 = _s44_dword_47EB08; +			_s44_dword_47EB08 = -1; +			_timers[4] = getRandom(20) + 20; +		} +	} +	 +	if (_gameSys->getAnimationStatus(4) == 2) { +		if (_s44_dword_47EB0C == 0xFB) { +			setGrabCursorSprite(kItemSpring); +			_s44_dword_47EB04 = 0xF8; +		} +		if (_s44_dword_47EB04 != -1) { +			_gameSys->insertSequence(_s44_dword_47EB04, 1, _s44_dword_47EB0C, 1, kSeqSyncWait, 0, 0, 0); +			_gameSys->setAnimation(_s44_dword_47EB04, 1, 4); +			_s44_dword_47EB0C = _s44_dword_47EB04; +			_s44_dword_47EB04 = -1; +			_timers[5] = getRandom(20) + 20; +		} +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2) { +		switch (_toyUfoActionStatus) { +		case 6: +			_sceneDone = true; +			break; +		default: +			_toyUfoNextSequenceId = toyUfoGetSequenceId(); +			_gameSys->insertSequence(_toyUfoNextSequenceId | 0x10000, _toyUfoId + 1, +				_toyUfoSequenceId | 0x10000, _toyUfoId, +				kSeqSyncWait, 0, _toyUfoX - 274, _toyUfoY - 128); +			_toyUfoSequenceId = _toyUfoNextSequenceId; +			++_toyUfoId; +			_gameSys->setAnimation(_toyUfoNextSequenceId | 0x10000, _toyUfoId, 3); +			break; +		} +		_toyUfoActionStatus = -1; +	} +	 +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene45.cpp b/engines/gnap/scenes/scene45.cpp new file mode 100644 index 0000000000..ba583045e5 --- /dev/null +++ b/engines/gnap/scenes/scene45.cpp @@ -0,0 +1,430 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus			= 0, +	kHSExitUfoParty		= 1, +	kHSExitShoe			= 2, +	kHSExitRight		= 3, +	kHSExitDiscoBall	= 4, +	kHSDiscoBall		= 5, +	kHSDevice			= 6, +	kHSWalkArea1		= 7 +}; + +enum { +	kHSUfoExitLeft	= 1, +	kHSUfoExitRight	= 2, +	kHSUfoDevice	= 3 +}; + +int GnapEngine::scene45_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	_gameSys->setAnimation(0, 0, 2); +	_gameSys->setAnimation(0, 0, 3); +	_gameSys->setAnimation(0, 0, 4); +	_gameSys->setAnimation(0, 0, 5); +	return isFlag(23) ? 0xA2 : 0xA1; +} + +void GnapEngine::scene45_updateHotspots() { +	if (isFlag(12)) { +		setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED); +		setHotspot(kHSUfoExitLeft, 0, 0, 10, 599, SF_EXIT_L_CURSOR); +		setHotspot(kHSUfoExitRight, 794, 0, 799, 599, SF_EXIT_R_CURSOR | SF_DISABLED); +		setDeviceHotspot(kHSUfoDevice, -1, 534, -1, 599); +		_hotspotsCount = 4; +	} else { +		setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +		setHotspot(kHSExitUfoParty, 150, 580, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9); +		setHotspot(kHSExitShoe, 0, 100, 10, 599, SF_EXIT_L_CURSOR, 0, 8); +		setHotspot(kHSExitRight, 794, 100, 799, 599, SF_EXIT_R_CURSOR | SF_DISABLED, 10, 8); +		setHotspot(kHSExitDiscoBall, 200, 0, 600, 10, SF_DISABLED); +		setHotspot(kHSDiscoBall, 370, 10, 470, 125, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 7); +		setHotspot(kHSWalkArea1, 0, 0, 800, 472); +		setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +		if (isFlag(22)) { +			_hotspots[kHSPlatypus].flags = SF_DISABLED; +			_hotspots[kHSExitUfoParty].flags = SF_DISABLED; +			_hotspots[kHSExitShoe].flags = SF_DISABLED; +			_hotspots[kHSExitRight].flags = SF_DISABLED; +			_hotspots[kHSExitDiscoBall].flags = SF_EXIT_U_CURSOR; +		} +		if (isFlag(23) || isFlag(22)) +			_hotspots[kHSDiscoBall].flags = SF_DISABLED; +		_hotspotsCount = 8; +	} +} + +void GnapEngine::scene45_run() { + +	if (!isSoundPlaying(0x1094A)) +		playSound(0x1094A, 1); +	 +	queueInsertDeviceIcon(); + +	_gameSys->insertSequence(0x96, 1, 0, 0, kSeqNone, 0, 0, 0); +	_gameSys->setAnimation(0x96, 1, 3); +	_gameSys->insertSequence(0x99, 1, 0, 0, kSeqNone, 0, 0, 0); +	_gameSys->setAnimation(0x99, 1, 4); +	_s45_dword_4749BC = 0x8F; +	_gameSys->setAnimation(0x8F, 1, 2); +	_gameSys->insertSequence(_s45_dword_4749BC, 1, 0, 0, kSeqNone, 0, 0, 0); +	 +	if (isFlag(12)) { +		_toyUfoId = 0; +		_toyUfoActionStatus = -1; +		_toyUfoSequenceId = toyUfoGetSequenceId(); +		_toyUfoNextSequenceId = _toyUfoSequenceId; +		if (_prevSceneNum == 46) +			_toyUfoX = 30; +		else +			_toyUfoX = 770; +		_gameSys->setAnimation(_toyUfoSequenceId | 0x10000, _toyUfoId, 5); +		_gameSys->insertSequence(_toyUfoSequenceId | 0x10000, _toyUfoId, 0, 0, kSeqNone, 0, _toyUfoX - 274, _toyUfoY - 128); +		endSceneInit(); +	} else if (isFlag(22)) { +		_gnapSequenceId = 0x9E; +		_gnapSequenceDatNum = 0; +		_gnapId = 1; +		_gameSys->setAnimation(0x9E, 1, 0); +		_gnapActionStatus = 1; +		_gameSys->insertSequence(_gnapSequenceId, _gnapId, 0, 0, kSeqNone, 0, 0, 0); +		initBeaverPos(4, 8, 0); +		endSceneInit(); +	} else if (_prevSceneNum == 46) { +		initGnapPos(-1, 8, 7); +		initBeaverPos(-1, 9, 5); +		endSceneInit(); +		platypusWalkTo(4, 8, -1, 0x107C2, 1); +		gnapWalkTo(2, 7, -1, 0x107B9, 1); +	} else if (_prevSceneNum == 41) { +		initGnapPos(11, 8, 7); +		initBeaverPos(11, 9, 5); +		endSceneInit(); +		platypusWalkTo(4, 8, -1, 0x107D2, 1); +		gnapWalkTo(10, 9, -1, 0x107BA, 1); +	} else { +		initGnapPos(2, 11, 7); +		initBeaverPos(6, 11, 5); +		endSceneInit(); +		platypusWalkTo(4, 8, -1, 0x107C2, 1); +		gnapWalkTo(2, 7, -1, 0x107B9, 1); +	} +	 +	if (!isFlag(21) && !isFlag(12)) { +		setFlag(21); +		setGrabCursorSprite(-1); +		_gameSys->setAnimation(0x9D, _gnapId, 0); +		_gameSys->insertSequence(0x9D, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +		while (_gameSys->getAnimationStatus(0) != 2) { +			gameUpdateTick(); +			if (_gameSys->getAnimationStatus(2) == 2) { +				_gameSys->setAnimation(0, 0, 2); +				_gnapRandomValue = getRandom(7); +				_s45_dword_4749C0 = _gnapRandomValue + 0x8F; +				_gameSys->insertSequence(_gnapRandomValue + 0x8F, 1, _s45_dword_4749BC, 1, kSeqSyncWait, 0, 0, 0); +				_gameSys->setAnimation(_s45_dword_4749C0, 1, 2); +				_s45_dword_4749BC = _s45_dword_4749C0; +			} +			if (_gameSys->getAnimationStatus(3) == 2 && _gameSys->getAnimationStatus(4) == 2) { +				_gameSys->insertSequence(0x96, 1, 0x96, 1, kSeqSyncWait, 0, 0, 0); +				_gameSys->setAnimation(0x96, 1, 3); +				_gameSys->insertSequence(0x99, 1, 0x99, 1, kSeqSyncWait, 0, 0, 0); +				_gameSys->setAnimation(0x99, 1, 4); +			} +		} +		_gnapSequenceId = 0x9D; +		_gnapSequenceDatNum = 0; +		hideCursor(); +		addFullScreenSprite(0x8A, 255); +		_gameSys->setAnimation(0xA0, 256, 0); +		_gameSys->insertSequence(0xA0, 256, 0, 0, kSeqNone, 0, 0, 0); +		while (_gameSys->getAnimationStatus(0) != 2) +			gameUpdateTick(); +		_gameSys->setAnimation(0x107BD, _gnapId, 0); +		_gameSys->insertSequence(0x107BD, _gnapId, +			makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, +			kSeqSyncWait, 0, 75 * _gnapX - _gnapGridX, 48 * _gnapY - _gnapGridY); +		removeFullScreenSprite(); +		showCursor(); +		_gnapSequenceId = 0x7BD; +		_gnapSequenceDatNum = 1; +	} +	 +	playBeaverSequence(0x9A); +	_gameSys->setAnimation(_beaverSequenceId, _beaverId, 1); +	 +	while (!_sceneDone) { +		 +		if (!isSoundPlaying(0x1094A)) +			playSound(0x1094A, 1); +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 0, -1, -1, -1, -1); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		if (isFlag(12)) { + +			switch (_sceneClickedHotspot) { + +			case kHSUfoExitLeft: +				if (_toyUfoActionStatus < 0) { +					_isLeavingScene = 1; +					_toyUfoActionStatus = 2; +					_newSceneNum = 46; +					toyUfoFlyTo(-35, -1, -35, 799, 0, 300, 5); +				} +				break; + +			case kHSUfoExitRight: +				if (_toyUfoActionStatus < 0) { +					_isLeavingScene = 1; +					_toyUfoActionStatus = 2; +					_newSceneNum = 41; +					toyUfoFlyTo(835, -1, 0, 835, 0, 300, 5); +				} +				break; + +			case kHSUfoDevice: +				runMenu(); +				scene45_updateHotspots(); +				break; + +			} + +		} else { + +			switch (_sceneClickedHotspot) { + +			case kHSDevice: +				runMenu(); +				scene45_updateHotspots(); +				break; +			 +			case kHSPlatypus: +				if (_gnapActionStatus < 0) { +					if (_grabCursorSpriteIndex >= 0) { +						playGnapImpossible(_platX, _platY); +					} else { +						switch (_verbCursor) { +						case LOOK_CURSOR: +							playGnapMoan1(_platX, _platY); +							break; +						case GRAB_CURSOR: +							gnapKissPlatypus(0); +							playBeaverSequence(0x9A); +							_gameSys->setAnimation(_beaverSequenceId, _beaverId, 1); +							break; +						case TALK_CURSOR: +							playGnapBrainPulsating(_platX, _platY); +							playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +							break; +						case PLAT_CURSOR: +							playGnapImpossible(_platX, _platY); +							break; +						} +					} +				} +				break; + +			case kHSExitUfoParty: +				if (_gnapActionStatus < 0) { +					_isLeavingScene = 1; +					gnapWalkTo(_gnapX, _hotspotsWalkPos[kHSExitUfoParty].y, 0, 0x107AE, 1); +					_gnapActionStatus = 0; +					_newSceneNum = 40; +				} +				break; +			 +			case kHSExitShoe: +				if (_gnapActionStatus < 0) { +					_isLeavingScene = 1; +					gnapWalkTo(_hotspotsWalkPos[kHSExitShoe].x, _gnapY, 0, 0x107AF, 1); +					_gnapActionStatus = 0; +					platypusWalkTo(_hotspotsWalkPos[kHSExitShoe].x, _platY, -1, 0x107CF, 1); +					_newSceneNum = 46; +				} +				break; +			 +			case kHSExitRight: +				if (_gnapActionStatus < 0) { +					_isLeavingScene = 1; +					gnapWalkTo(_hotspotsWalkPos[kHSExitRight].x, _gnapY, 0, 0x107AB, 1); +					_gnapActionStatus = 0; +					platypusWalkTo(_hotspotsWalkPos[kHSExitRight].x, _platY, -1, 0x107CD, 1); +					_newSceneNum = 41; +				} +				break; + +			case kHSExitDiscoBall: +				clearFlag(22); +				setFlag(23); +				_sceneDone = true; +				_newSceneNum = 54; +				break; + +			case kHSDiscoBall: +				if (_gnapActionStatus < 0) { +					if (_grabCursorSpriteIndex == kItemSpring) { +						gnapWalkTo(_hotspotsWalkPos[kHSDiscoBall].x, _hotspotsWalkPos[kHSDiscoBall].y, 0, 0x9F, 5); +						_gnapActionStatus = 1; +						setGrabCursorSprite(-1); +						invRemove(kItemSpring); +					} else if (_grabCursorSpriteIndex >= 0) { +						playGnapShowItem(_grabCursorSpriteIndex, 5, 0); +					} else { +						switch (_verbCursor) { +						case LOOK_CURSOR: +							playGnapScratchingHead(5, 0); +							break; +						case GRAB_CURSOR: +						case TALK_CURSOR: +						case PLAT_CURSOR: +							playGnapImpossible(0, 0); +							break; +						} +					} +				} +				break; +			 +			case kHSWalkArea1: +				if (_gnapActionStatus < 0) +					gnapWalkTo(-1, -1, -1, -1, 1); +				break; +			 +			} +		 +		} + +		if (_mouseClickState.left && _gnapActionStatus < 0) { +			_mouseClickState.left = false; +			if (isFlag(12)) { +				_toyUfoActionStatus = 3; +				toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 5); +			} else { +				gnapWalkTo(-1, -1, -1, -1, 1); +			} +		} +	 +		scene45_updateAnimations(); +		toyUfoCheckTimer(); +	 +		if (!_isLeavingScene && _gnapActionStatus < 0 && !isFlag(12)) +			updateGnapIdleSequence(); +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene45_updateHotspots(); +		} +	 +		gameUpdateTick(); + +	} + +	_sceneWaiting = 0; + +} + +void GnapEngine::scene45_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case 0: +			_sceneDone = true; +			break; +		case 1: +			_sceneWaiting = 1; +			setFlag(22); +			scene45_updateHotspots(); +			_gameSys->insertSequence(0x9E, _gnapId, makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, kSeqSyncWait, 0, 0, 0); +			_gnapSequenceId = 0x9E; +			_gnapSequenceDatNum = 0; +			_gameSys->setAnimation(0x9E, _gnapId, 0); +			break; +		default: +			_gnapActionStatus = -1; +			break; +		} +	} +	 +	if (_gameSys->getAnimationStatus(1) == 2) { +		_gameSys->setAnimation(0, 0, 1); +		if (getRandom(2) != 0) +			playBeaverSequence(0x9B); +		else +			playBeaverSequence(0x9C); +		_gameSys->setAnimation(_beaverSequenceId, _beaverId, 1); +	} +	 +	if (_gameSys->getAnimationStatus(2) == 2) { +		_gameSys->setAnimation(0, 0, 2); +		_gnapRandomValue = getRandom(7); +		_s45_dword_4749C0 = _gnapRandomValue + 0x8F; +		_gameSys->insertSequence(_gnapRandomValue + 0x8F, 1, _s45_dword_4749BC, 1, kSeqSyncWait, 0, 0, 0); +		_gameSys->setAnimation(_s45_dword_4749C0, 1, 2); +		_s45_dword_4749BC = _s45_dword_4749C0; +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2 && _gameSys->getAnimationStatus(4) == 2) { +		_gameSys->insertSequence(0x96, 1, 0x96, 1, kSeqSyncWait, 0, 0, 0); +		_gameSys->setAnimation(0x96, 1, 3); +		_gameSys->insertSequence(0x99, 1, 0x99, 1, kSeqSyncWait, 0, 0, 0); +		_gameSys->setAnimation(0x99, 1, 4); +	} +	 +	if (_gameSys->getAnimationStatus(5) == 2) { +		switch (_toyUfoActionStatus) { +		case 2: +			_sceneDone = true; +			break; +		default: +			_toyUfoNextSequenceId = toyUfoGetSequenceId(); +			_gameSys->insertSequence(_toyUfoNextSequenceId | 0x10000, _toyUfoId + 1, +				_toyUfoSequenceId | 0x10000, _toyUfoId, +				kSeqSyncWait, 0, _toyUfoX - 274, _toyUfoY - 128); +			_toyUfoSequenceId = _toyUfoNextSequenceId; +			++_toyUfoId; +			_gameSys->setAnimation(_toyUfoNextSequenceId | 0x10000, _toyUfoId, 5); +			break; +		} +		_toyUfoActionStatus = -1; +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene46.cpp b/engines/gnap/scenes/scene46.cpp new file mode 100644 index 0000000000..86855bbdf2 --- /dev/null +++ b/engines/gnap/scenes/scene46.cpp @@ -0,0 +1,378 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +enum { +	kHSPlatypus			= 0, +	kHSExitUfoParty		= 1, +	kHSExitKissinBooth	= 2, +	kHSExitDisco		= 3, +	kHSSackGuy			= 4, +	kHSItchyGuy			= 5, +	kHSDevice			= 6, +	kHSWalkArea1		= 7 +}; + +enum { +	kHSUfoExitLeft	= 1, +	kHSUfoExitRight	= 2, +	kHSUfoDevice	= 3 +}; + +int GnapEngine::scene46_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	_gameSys->setAnimation(0, 0, 2); +	_gameSys->setAnimation(0, 0, 3); +	_gameSys->setAnimation(0, 0, 4); +	return 0x4E; +} + +void GnapEngine::scene46_updateHotspots() { +	if (isFlag(12)) { +		setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_DISABLED); +		setHotspot(kHSUfoExitLeft, 0, 0, 10, 599, SF_EXIT_L_CURSOR); +		setHotspot(kHSUfoExitRight, 790, 0, 799, 599, SF_EXIT_R_CURSOR); +		setDeviceHotspot(kHSUfoDevice, -1, 534, -1, 599); +		_hotspotsCount = 4; +	} else { +		setHotspot(kHSPlatypus, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +		setHotspot(kHSExitUfoParty, 150, 580, 650, 600, SF_EXIT_D_CURSOR | SF_WALKABLE, 5, 9); +		setHotspot(kHSExitKissinBooth, 0, 100, 10, 599, SF_EXIT_L_CURSOR, 0, 8); +		setHotspot(kHSExitDisco, 790, 100, 799, 599, SF_EXIT_R_CURSOR, 10, 8); +		setHotspot(kHSSackGuy, 180, 370, 235, 490, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 3, 8); +		setHotspot(kHSItchyGuy, 535, 210, 650, 480, SF_PLAT_CURSOR | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR, 6, 8); +		setHotspot(kHSWalkArea1, 0, 0, 800, 485); +		setDeviceHotspot(kHSDevice, -1, -1, -1, -1); +		_hotspotsCount = 8; +	} +} + +void GnapEngine::scene46_run() { + +	queueInsertDeviceIcon(); + +	_gameSys->insertSequence(0x4D, 0, 0, 0, kSeqLoop, 0, 0, 0); +	 +	_s46_dword_47EB18 = 0x4B; +	_s46_dword_47EB20 = -1; +	_gameSys->setAnimation(0x4B, 1, 3); +	_gameSys->insertSequence(_s46_dword_47EB18, 1, 0, 0, kSeqNone, 0, 0, 0); +	 +	_s46_dword_47EB24 = 0x47; +	_s46_dword_47EB1C = -1; +	_gameSys->setAnimation(0x47, 1, 4); +	_gameSys->insertSequence(_s46_dword_47EB24, 1, 0, 0, kSeqNone, 0, 0, 0); +	 +	if (isFlag(12)) { +		_toyUfoId = 0; +		_toyUfoActionStatus = -1; +		_toyUfoSequenceId = toyUfoGetSequenceId(); +		_toyUfoNextSequenceId = _toyUfoSequenceId; +		if (_prevSceneNum == 44) +			_toyUfoX = 30; +		else +			_toyUfoX = 770; +		_gameSys->setAnimation(_toyUfoSequenceId | 0x10000, _toyUfoId, 2); +		_gameSys->insertSequence(_toyUfoSequenceId | 0x10000, _toyUfoId, 0, 0, kSeqNone, 0, _toyUfoX - 274, _toyUfoY - 128); +		endSceneInit(); +	} else if (_prevSceneNum == 44) { +		initGnapPos(-1, 8, 7); +		initBeaverPos(-1, 8, 5); +		endSceneInit(); +		platypusWalkTo(1, 8, -1, 0x107C2, 1); +		gnapWalkTo(2, 8, -1, 0x107B9, 1); +	} else if (_prevSceneNum == 45) { +		initGnapPos(11, 8, 7); +		initBeaverPos(12, 8, 5); +		endSceneInit(); +		gnapWalkTo(8, 8, -1, 0x107BA, 1); +		platypusWalkTo(9, 8, -1, 0x107D2, 1); +	} else { +		initGnapPos(5, 11, 7); +		initBeaverPos(6, 11, 5); +		endSceneInit(); +		platypusWalkTo(5, 8, -1, 0x107C2, 1); +		gnapWalkTo(6, 8, -1, 0x107BA, 1); +	} + +	_timers[4] = getRandom(50) + 80; +	_timers[5] = getRandom(50) + 80; + +	while (!_sceneDone) { +	 +		if (!isSoundPlaying(0x1094B)) +			playSound(0x1094B, 1); +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 0, -1, -1, -1, -1); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		if (isFlag(12)) { + +			switch (_sceneClickedHotspot) { + +			case kHSUfoExitLeft: +				if (_toyUfoActionStatus < 0) { +					_isLeavingScene = 1; +					_toyUfoActionStatus = 3; +					_newSceneNum = 44; +					toyUfoFlyTo(-35, -1, -35, 799, 0, 300, 2); +				} +				break; + +			case kHSUfoExitRight: +				if (_toyUfoActionStatus < 0) { +					_isLeavingScene = 1; +					_toyUfoActionStatus = 3; +					_newSceneNum = 45; +					toyUfoFlyTo(835, -1, 0, 835, 0, 300, 2); +				} +				break; + +			case kHSUfoDevice: +				runMenu(); +				scene46_updateHotspots(); +				break; +			} + +		} else { + +			switch (_sceneClickedHotspot) { + +			case kHSDevice: +				runMenu(); +				scene46_updateHotspots(); +				break; + +			case kHSPlatypus: +				if (_gnapActionStatus < 0) { +					if (_grabCursorSpriteIndex >= 0) { +						playGnapImpossible(_platX, _platY); +					} else { +						switch (_verbCursor) { +						case LOOK_CURSOR: +							playGnapMoan1(_platX, _platY); +							break; +						case GRAB_CURSOR: +							gnapKissPlatypus(0); +							break; +						case TALK_CURSOR: +							playGnapBrainPulsating(_platX, _platY); +							playBeaverSequence(getBeaverSequenceId(0, 0, 0) | 0x10000); +							break; +						case PLAT_CURSOR: +							playGnapImpossible(_platX, _platY); +							break; +						} +					} +				} +				break; + +			case kHSSackGuy: +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSSackGuy].x, _hotspotsWalkPos[kHSSackGuy].y, 2, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan1(_hotspotsWalkPos[kHSSackGuy].x + 1, 0); +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 5; +						gnapWalkTo(_hotspotsWalkPos[kHSSackGuy].x, _hotspotsWalkPos[kHSSackGuy].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = 2; +						break; +					case GRAB_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +				break; + +			case kHSItchyGuy: +				if (_grabCursorSpriteIndex >= 0) { +					playGnapShowCurrItem(_hotspotsWalkPos[kHSItchyGuy].x, _hotspotsWalkPos[kHSItchyGuy].y, 7, 0); +				} else { +					switch (_verbCursor) { +					case LOOK_CURSOR: +						playGnapMoan1(_hotspotsWalkPos[kHSItchyGuy].x - 1, 0); +						break; +					case TALK_CURSOR: +						_gnapIdleFacing = 7; +						gnapWalkTo(_hotspotsWalkPos[kHSItchyGuy].x, _hotspotsWalkPos[kHSItchyGuy].y, 0, getGnapSequenceId(gskBrainPulsating, 0, 0) | 0x10000, 1); +						_gnapActionStatus = 1; +						break; +					case GRAB_CURSOR: +					case PLAT_CURSOR: +						playGnapImpossible(0, 0); +						break; +					} +				} +				break; + +			case kHSExitUfoParty: +				_isLeavingScene = 1; +				gnapWalkTo(_gnapX, _hotspotsWalkPos[kHSExitUfoParty].y, 0, 0x107AE, 1); +				_gnapActionStatus = 0; +				_newSceneNum = 40; +				break; + +			case kHSExitKissinBooth: +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[kHSExitKissinBooth].x, _gnapY, 0, 0x107AF, 1); +				_gnapActionStatus = 0; +				platypusWalkTo(_hotspotsWalkPos[kHSExitKissinBooth].x, _platY, -1, 0x107CF, 1); +				_newSceneNum = 44; +				break; + +			case kHSExitDisco: +				_isLeavingScene = 1; +				gnapWalkTo(_hotspotsWalkPos[kHSExitDisco].x, _gnapY, 0, 0x107AB, 1); +				_gnapActionStatus = 0; +				platypusWalkTo(_hotspotsWalkPos[kHSExitDisco].x, _platY, -1, 0x107CD, 1); +				_newSceneNum = 45; +				break; + +			case kHSWalkArea1: +				if (_gnapActionStatus < 0) +					gnapWalkTo(-1, -1, -1, -1, 1); +					break; + +			} + +		} +	 +		if (_mouseClickState.left && _gnapActionStatus < 0) { +			_mouseClickState.left = false; +			if (isFlag(12)) { +				_toyUfoActionStatus = 4; +				toyUfoFlyTo(-1, -1, 0, 799, 0, 300, 2); +			} else { +				gnapWalkTo(-1, -1, -1, -1, 1); +			} +		} +	 +		scene46_updateAnimations(); +		 +		toyUfoCheckTimer(); +	 +		if (!_isLeavingScene) { +			if (_beaverActionStatus < 0 && !isFlag(12)) +				updateBeaverIdleSequence(); +			if (_gnapActionStatus < 0 && !isFlag(12)) +				updateGnapIdleSequence(); +			if (!_timers[4]) { +				_timers[4] = getRandom(50) + 80; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s46_dword_47EB1C == -1) { +					_gnapRandomValue = getRandom(2); +					if (_gnapRandomValue != 0) +						_s46_dword_47EB1C = 0x49; +					else +						_s46_dword_47EB1C = 0x48; +				} +			} +			if (!_timers[5]) { +				_timers[5] = getRandom(50) + 80; +				if (_gnapActionStatus < 0 && _beaverActionStatus < 0 && _s46_dword_47EB20 == -1) +					_s46_dword_47EB20 = 0x4C; +			} +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene46_updateHotspots(); +		} +		 +		gameUpdateTick(); +	 +	} + +} + +void GnapEngine::scene46_updateAnimations() { + +	if (_gameSys->getAnimationStatus(0) == 2) { +		_gameSys->setAnimation(0, 0, 0); +		switch (_gnapActionStatus) { +		case 0: +			_sceneDone = true; +			break; +		case 1: +			_s46_dword_47EB1C = 0x46; +			break; +		case 2: +			_s46_dword_47EB20 = 0x4A; +			break; +		} +		_gnapActionStatus = -1; +	} +	 +	if (_gameSys->getAnimationStatus(3) == 2 && _s46_dword_47EB20 != -1) { +		_gameSys->insertSequence(_s46_dword_47EB20, 1, _s46_dword_47EB18, 1, kSeqSyncWait, 0, 0, 0); +		_gameSys->setAnimation(_s46_dword_47EB20, 1, 3); +		_s46_dword_47EB18 = _s46_dword_47EB20; +		_s46_dword_47EB20 = -1; +		_timers[5] = getRandom(50) + 80; +	} +	 +	if (_gameSys->getAnimationStatus(4) == 2 && _s46_dword_47EB1C != -1) { +		_gameSys->insertSequence(_s46_dword_47EB1C, 1, _s46_dword_47EB24, 1, kSeqSyncWait, 0, 0, 0); +		_gameSys->setAnimation(_s46_dword_47EB1C, 1, 4); +		_s46_dword_47EB24 = _s46_dword_47EB1C; +		_s46_dword_47EB1C = -1; +		_timers[4] = getRandom(50) + 80; +	} +	 +	if (_gameSys->getAnimationStatus(2) == 2) { +		switch (_toyUfoActionStatus) { +		case 3: +			_sceneDone = true; +			break; +		default: +			_toyUfoNextSequenceId = toyUfoGetSequenceId(); +			_gameSys->insertSequence(_toyUfoNextSequenceId | 0x10000, _toyUfoId + 1, +				_toyUfoSequenceId | 0x10000, _toyUfoId, +				kSeqSyncWait, 0, _toyUfoX - 274, _toyUfoY - 128); +			_toyUfoSequenceId = _toyUfoNextSequenceId; +			++_toyUfoId; +			_gameSys->setAnimation(_toyUfoNextSequenceId | 0x10000, _toyUfoId, 2); +			break; +		} +		_toyUfoActionStatus = -1; +	} + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene47.cpp b/engines/gnap/scenes/scene47.cpp new file mode 100644 index 0000000000..2e735e3650 --- /dev/null +++ b/engines/gnap/scenes/scene47.cpp @@ -0,0 +1,171 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +void GnapEngine::scene47_initCutscene1() { +	_s99_dword_47F370[0] = 0x301; +	_s99_dword_47F370[1] = 0x305; +	_s99_dword_47F370[2] = 0x302; +	_s99_dword_47F370[3] = 0x304; +	_s99_dword_47F370[4] = 0x300; +	_s99_dword_47F2F0[0] = 3; +	_s99_dword_47F2F0[1] = 0; +	_s99_dword_47F2F0[2] = 1; +	_s99_dword_47F2F0[3] = 0; +	_s99_dword_47F2F0[4] = 2; +	_s99_dword_47F330[0] = 1; +	_s99_dword_47F330[1] = 1; +	_s99_dword_47F330[2] = 1; +	_s99_dword_47F330[3] = 1; +	_s99_dword_47F330[4] = 1; +	_s99_canSkip[0] = 0; +	_s99_canSkip[1] = 0; +	_s99_canSkip[2] = 0; +	_s99_canSkip[3] = 0; +	_s99_canSkip[4] = 0; +	_s99_itemsCount = 5; +} + +void GnapEngine::scene47_initCutscene2() { +	_s99_dword_47F370[0] = 0x306; +	_s99_dword_47F370[1] = 0x309; +	_s99_dword_47F370[2] = 0x307; +	_s99_dword_47F370[3] = 0x308; +	_s99_dword_47F370[4] = 0x30A; +	_s99_dword_47F2F0[0] = 0x8E; +	_s99_dword_47F2F0[1] = 0x90; +	_s99_dword_47F2F0[2] = 0x8F; +	_s99_dword_47F2F0[3] = 0x91; +	_s99_dword_47F330[0] = 2; +	_s99_dword_47F330[1] = 1; +	_s99_dword_47F330[2] = 1; +	_s99_dword_47F330[3] = 1; +	_s99_canSkip[0] = 0; +	_s99_canSkip[1] = 0; +	_s99_canSkip[2] = 0; +	_s99_canSkip[3] = 0; +	_s99_itemsCount = 4; +} + +void GnapEngine::scene47_initCutscene3() { +	_s99_dword_47F370[0] = 0x320; +	_s99_dword_47F370[1] = 0x321; +	_s99_dword_47F2F0[0] = 0x142; +	_s99_dword_47F2F0[1] = 0x143; +	_s99_dword_47F330[0] = 1; +	_s99_dword_47F330[1] = 1; +	_s99_canSkip[0] = 0; +	_s99_canSkip[1] = 0; +	_s99_itemsCount = 2; +} + +void GnapEngine::scene47_initCutscene4() { +	_s99_dword_47F370[0] = 0x30C; +	_s99_dword_47F370[1] = 0x30D; +	_s99_dword_47F370[2] = 0x30B; +	_s99_dword_47F2F0[0] = 0x142; +	_s99_dword_47F2F0[1] = 0x141; +	_s99_dword_47F2F0[2] = 0x177; +	_s99_dword_47F330[0] = 1; +	_s99_dword_47F330[1] = 1; +	_s99_dword_47F330[2] = 1; +	_s99_canSkip[0] = 0; +	_s99_canSkip[1] = 0; +	_s99_canSkip[2] = 0; +	_s99_itemsCount = 3; +} + +void GnapEngine::scene47_initCutscene5() { +	_s99_dword_47F370[0] = 0x30E; +	_s99_dword_47F370[1] = 0x30F; +	_s99_dword_47F370[2] = 0x310; +	_s99_dword_47F370[3] = 0x311; +	_s99_dword_47F2F0[0] = 0x206; +	_s99_dword_47F2F0[1] = 0x207; +	_s99_dword_47F330[0] = 3; +	_s99_dword_47F330[1] = 1; +	_s99_canSkip[0] = 0; +	_s99_canSkip[1] = 0; +	_s99_itemsCount = 2; +} + +void GnapEngine::scene47_initCutscene6() { +	_s99_dword_47F370[0] = 0x31E; +	_s99_dword_47F370[1] = 0x31F; +	_s99_dword_47F2F0[0] = 0x2FA; +	_s99_dword_47F330[0] = 2; +	_s99_canSkip[0] = 0; +	_s99_itemsCount = 1; +} + +void GnapEngine::scene47_initCutscene7() { +	int v1 = 4, v0, v4, v2, v3; +	 +	_s99_dword_47F370[0] = 0x316; +	_s99_dword_47F370[1] = 0x31A; +	_s99_dword_47F370[2] = 0x314; +	_s99_dword_47F370[3] = 0x31B; +	v1 = 4; +	if (!isFlag(3)) { +		_s99_dword_47F370[4] = 0x31C; +		v1 = 5; +	} +	if (!isFlag(26)) +		_s99_dword_47F370[v1++] = 0x31D; +	v4 = v1; +	_s99_dword_47F370[v1] = 0x319; +	v0 = v1 + 1; +	v3 = v0; +	_s99_dword_47F370[v0++] = 0x317; +	_s99_dword_47F370[v0++] = 0x312; +	_s99_dword_47F370[v0] = 0x31A; +	v2 = v0 + 1; +	if (!isFlag(3)) +		_s99_dword_47F370[v2++] = 0x31C; +	if (!isFlag(26)) +		_s99_dword_47F370[v2++] = 0x31D; +	_s99_dword_47F370[v2] = 0x313; +	_s99_dword_47F370[v2 + 1] = 0x315; +	_s99_dword_47F2F0[0] = 0x2B8; +	_s99_dword_47F2F0[1] = 0x20C; +	_s99_dword_47F2F0[2] = 0x2B8; +	_s99_dword_47F2F0[3] = 0x20B; +	_s99_dword_47F2F0[4] = 0x20B; +	_s99_dword_47F330[0] = v4; +	_s99_dword_47F330[1] = 1; +	_s99_dword_47F330[2] = v2 - v3; +	_s99_dword_47F330[3] = 1; +	_s99_dword_47F330[4] = 1; +	_s99_canSkip[0] = 0; +	_s99_canSkip[1] = 0; +	_s99_canSkip[2] = 0; +	_s99_canSkip[3] = 0; +	_s99_canSkip[4] = 0; +	_s99_itemsCount = 5; +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene48.cpp b/engines/gnap/scenes/scene48.cpp new file mode 100644 index 0000000000..3b24d57a8c --- /dev/null +++ b/engines/gnap/scenes/scene48.cpp @@ -0,0 +1,85 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +void GnapEngine::scene48_initCutscene() { +	_s99_dword_47F370[0] = 390; +	_s99_dword_47F370[1] = 391; +	_s99_dword_47F370[2] = 392; +	_s99_dword_47F370[3] = 393; +	_s99_dword_47F370[4] = 394; +	_s99_dword_47F370[5] = 395; +	_s99_dword_47F370[6] = 396; +	_s99_dword_47F370[7] = 397; +	_s99_dword_47F370[8] = 398; +	_s99_dword_47F370[9] = 399; +	_s99_dword_47F370[10] = 400; +	_s99_dword_47F370[11] = 401; +	_s99_dword_47F370[12] = 402; +	_s99_dword_47F2F0[0] = 238; +	_s99_dword_47F2F0[1] = 42; +	_s99_dword_47F2F0[2] = 2; +	_s99_dword_47F2F0[3] = 37; +	_s99_dword_47F2F0[4] = 35; +	_s99_dword_47F2F0[5] = 38; +	_s99_dword_47F2F0[6] = 39; +	_s99_dword_47F2F0[7] = 40; +	_s99_dword_47F2F0[8] = 41; +	_s99_dword_47F2F0[9] = 36; +	_s99_dword_47F2F0[10] = 41; +	_s99_dword_47F2F0[11] = 388; +	_s99_dword_47F2F0[12] = 387; +	_s99_dword_47F330[0] = 1; +	_s99_dword_47F330[1] = 1; +	_s99_dword_47F330[2] = 1; +	_s99_dword_47F330[3] = 1; +	_s99_dword_47F330[4] = 1; +	_s99_dword_47F330[5] = 1; +	_s99_dword_47F330[6] = 1; +	_s99_dword_47F330[7] = 1; +	_s99_dword_47F330[8] = 1; +	_s99_dword_47F330[9] = 1; +	_s99_dword_47F330[10] = 1; +	_s99_dword_47F330[11] = 1; +	_s99_dword_47F330[12] = 1; +	_s99_canSkip[0] = 0; +	_s99_canSkip[1] = 0; +	_s99_canSkip[2] = 0; +	_s99_canSkip[3] = 0; +	_s99_canSkip[4] = 0; +	_s99_canSkip[5] = 0; +	_s99_canSkip[6] = 0; +	_s99_canSkip[7] = 0; +	_s99_canSkip[8] = 0; +	_s99_canSkip[9] = 0; +	_s99_canSkip[10] = 0; +	_s99_canSkip[11] = 0; +	_s99_canSkip[12] = 0; +	_s99_itemsCount = 13; +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene49.cpp b/engines/gnap/scenes/scene49.cpp new file mode 100644 index 0000000000..e8415bbc9f --- /dev/null +++ b/engines/gnap/scenes/scene49.cpp @@ -0,0 +1,513 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +struct ObstacleDef { +	int sequenceId, ticks; +}; + +static const ObstacleDef kObstacleDefs[] = { +	{0xB4, 15}, {0xCB, 14}, {0xCD, 13}, {0xCF, 15}, {0xBA, 14}, +	{0xCD, 13}, {0xCF, 12}, {0xCB, 15}, {0xBD, 13}, {0xCF, 12}, +	{0xCD, 11}, {0xCB, 15}, {0xB7, 12}, {0xCD, 11}, {0xCB, 10}, +	{0xCF, 15}, {0xCF, 14}, {0xBD, 13}, {0xCF, 12}, {0xCD, 11}, +	{0xCB, 15}, {0xCB, 13}, {0xB4, 12}, {0xCB, 11}, {0xCD, 10}, +	{0xCF, 15}, {0xCD, 12}, {0xBA, 12}, {0xCD, 12}, {0xCF, 12}, +	{0xCB, 15}, {0xCB,  9}, {0xCD,  9}, {0xCF,  9}, {0xCD,  9}, +	{0xCB,  9}, {0xCD,  9}, {0xCF,  5}, {0xBD, 13}, {0xCF,  8}, +	{0xCB,  8}, {0xCD, 15}, {0xB4,  1}, {0xBD,  7}, {0xCF,  7}, +	{0xCD,  7}, {0xCB,  7}, {0xCD,  7}, {0xCF, 15}, {0xCF, 15} +}; + +int GnapEngine::scene49_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	for (int i = 0; i < 5; ++i) +		_gameSys->setAnimation(0, 0, i + 2); +	_timers[2] = 0; +	_timers[0] = 0; +	_timers[1] = 0; +	clearKeyStatus1(28); +	clearKeyStatus1(54); +	clearKeyStatus1(52); +	return 0xD5; +} + +void GnapEngine::scene49_updateHotspots() { +	_hotspotsCount = 0; +} + +void GnapEngine::scene49_checkObstacles() { + +	if (_timers[2] == 0) { + +		if (_timers[3] == 0) +			for (int i = 0; i < 5; ++i) +				scene49_clearObstacle(i); + +		for (int j = 0; j < 5; ++j) { +			if (_s49_obstacles[j].currSequenceId == 0) { +				_timers[3] = 35; +				_s49_obstacles[j].currSequenceId = kObstacleDefs[_s49_obstacleIndex].sequenceId; +				switch (_s49_obstacles[j].currSequenceId) { +				case 0xB4: +					_s49_obstacles[j].laneNum = 1; +					_s49_obstacles[j].closerSequenceId = 180; +					_s49_obstacles[j].passedSequenceId = 181; +					_s49_obstacles[j].splashSequenceId = 182; +					_s49_obstacles[j].collisionSequenceId = 192; +					break; +				case 0xB7: +					_s49_obstacles[j].laneNum = 2; +					_s49_obstacles[j].closerSequenceId = 183; +					_s49_obstacles[j].passedSequenceId = 184; +					_s49_obstacles[j].splashSequenceId = 185; +					_s49_obstacles[j].collisionSequenceId = 193; +					break; +				case 0xBD: +					_s49_obstacles[j].laneNum = 3; +					_s49_obstacles[j].closerSequenceId = 189; +					_s49_obstacles[j].passedSequenceId = 190; +					_s49_obstacles[j].splashSequenceId = 191; +					_s49_obstacles[j].collisionSequenceId = 195; +					break; +				case 0xBA: +					_s49_obstacles[j].laneNum = 2; +					_s49_obstacles[j].closerSequenceId = 186; +					_s49_obstacles[j].passedSequenceId = 187; +					_s49_obstacles[j].splashSequenceId = 188; +					_s49_obstacles[j].collisionSequenceId = 194; +					break; +				case 0xCB: +					_s49_obstacles[j].laneNum = 1; +					_s49_obstacles[j].closerSequenceId = 203; +					_s49_obstacles[j].passedSequenceId = 204; +					_s49_obstacles[j].splashSequenceId = 0; +					_s49_obstacles[j].collisionSequenceId = 209; +					break; +				case 0xCD: +					_s49_obstacles[j].laneNum = 2; +					_s49_obstacles[j].closerSequenceId = 205; +					_s49_obstacles[j].passedSequenceId = 206; +					_s49_obstacles[j].splashSequenceId = 0; +					_s49_obstacles[j].collisionSequenceId = 210; +					break; +				case 0xCF: +					_s49_obstacles[j].laneNum = 3; +					_s49_obstacles[j].closerSequenceId = 207; +					_s49_obstacles[j].passedSequenceId = 208; +					_s49_obstacles[j].splashSequenceId = 0; +					_s49_obstacles[j].collisionSequenceId = 211; +					break; +				} +				_s49_obstacles[j].prevId = _s49_truckId; +				_s49_obstacles[j].currId = _s49_obstacles[j].prevId; +				_gameSys->setAnimation(_s49_obstacles[j].currSequenceId, _s49_obstacles[j].currId, j + 2); +				_gameSys->insertSequence(_s49_obstacles[j].currSequenceId, _s49_obstacles[j].currId, 0, 0, kSeqNone, 0, 0, -50); +				_timers[2] = kObstacleDefs[_s49_obstacleIndex].ticks; +				++_s49_obstacleIndex; +				if (_s49_obstacleIndex == 50) +					_s49_obstacleIndex = 0; +				break; +			} +		} + +	} + +} + +void GnapEngine::scene49_updateObstacle(int i) { + +	Scene49Obstacle &obstacle = _s49_obstacles[i]; +	 +	obstacle.currId = obstacle.prevId; +	 +	switch (obstacle.laneNum) { +	case 1: +		obstacle.prevId = _s49_truckId + 1; +		break; +	case 2: +		if (_s49_truckLaneNum != 2 && _s49_truckLaneNum != 3) +			obstacle.prevId = _s49_truckId - 1; +		else +			obstacle.prevId = _s49_truckId + 1; +		break; +	case 3: +		if (_s49_truckLaneNum != 1 && _s49_truckLaneNum != 2) +			obstacle.prevId = _s49_truckId; +		else +			obstacle.prevId = _s49_truckId - 1; +		break; +	} + +	if (obstacle.currSequenceId == obstacle.closerSequenceId) { +		if (_s49_truckLaneNum == obstacle.laneNum) { +			if (obstacle.splashSequenceId) { +				_gameSys->setAnimation(obstacle.collisionSequenceId, obstacle.prevId, i + 2); +				_gameSys->insertSequence(obstacle.collisionSequenceId, obstacle.prevId, +					obstacle.currSequenceId, obstacle.currId, +					kSeqSyncWait, 0, 0, -50); +				obstacle.currSequenceId = obstacle.collisionSequenceId; +				playSound(224, 0); +				scene49_increaseScore(30); +			} else if ((obstacle.laneNum == 1 && _s49_truckSequenceId == 0xB0) || +				(obstacle.laneNum == 2 && (_s49_truckSequenceId == 0xB1 || _s49_truckSequenceId == 0xB2)) || +				(obstacle.laneNum == 3 && _s49_truckSequenceId == 0xB3)) { +				_gameSys->setAnimation(obstacle.passedSequenceId, obstacle.prevId, i + 2); +				_gameSys->insertSequence(obstacle.passedSequenceId, obstacle.prevId, +					obstacle.currSequenceId, obstacle.currId, +					kSeqSyncWait, 0, 0, -50); +				obstacle.currSequenceId = obstacle.passedSequenceId; +			} else { +				_gameSys->setAnimation(obstacle.collisionSequenceId, 256, 0); +				_gameSys->setAnimation(obstacle.passedSequenceId, obstacle.prevId, i + 2); +				_gameSys->insertSequence(obstacle.passedSequenceId, obstacle.prevId, +					obstacle.currSequenceId, obstacle.currId, +					kSeqSyncWait, 0, 0, -50); +				_gameSys->insertSequence(obstacle.collisionSequenceId, 256, +					_s49_truckSequenceId, _s49_truckId, +					32, 0, 0, -50); +				_s49_truckSequenceId = obstacle.collisionSequenceId; +				_s49_truckId = 256; +				obstacle.currSequenceId = obstacle.passedSequenceId; +				playSound(225, 0); +				scene49_decreaseScore(30); +			} +		} else { +			_gameSys->setAnimation(obstacle.passedSequenceId, obstacle.prevId, i + 2); +			_gameSys->insertSequence(obstacle.passedSequenceId, obstacle.prevId, +				obstacle.currSequenceId, obstacle.currId, +				kSeqSyncWait, 0, 0, -50); +			obstacle.currSequenceId = obstacle.passedSequenceId; +		} +	} else if (obstacle.currSequenceId == obstacle.passedSequenceId) { +		if (_s49_truckLaneNum == obstacle.laneNum) { +			if (obstacle.splashSequenceId) { +				_gameSys->setAnimation(obstacle.collisionSequenceId, obstacle.prevId, i + 2); +				_gameSys->insertSequence(obstacle.collisionSequenceId, obstacle.prevId, +					obstacle.currSequenceId, obstacle.currId, +					kSeqSyncWait, 0, 0, -50); +				obstacle.currSequenceId = obstacle.collisionSequenceId; +				playSound(224, 0); +				scene49_increaseScore(30); +			} +		} else if (obstacle.splashSequenceId) { +			_gameSys->setAnimation(obstacle.splashSequenceId, obstacle.prevId, i + 2); +			_gameSys->insertSequence(obstacle.splashSequenceId, obstacle.prevId, +				obstacle.currSequenceId, obstacle.currId, +				kSeqSyncWait, 0, 0, -50); +			obstacle.currSequenceId = obstacle.splashSequenceId; +		} +	} else { +		_gameSys->setAnimation(0, 0, i + 2); +		scene49_clearObstacle(i); +	} +	 +} + +void GnapEngine::scene49_increaseScore(int amount) { +	if (_s49_scoreBarPos + amount <= 556) { +		_s49_scoreBarPos += amount; +		_gameSys->fillSurface(0, _s49_scoreBarPos, 508, amount, 22, 255, 0, 0); +	} +	_s49_scoreLevel = _s49_scoreBarPos + amount >= 556; +} + +void GnapEngine::scene49_decreaseScore(int amount) { +	if (_s49_scoreBarPos >= 226 && _s49_scoreLevel == 0) { +		if (_s49_scoreBarFlash) +			scene49_refreshScoreBar(); +		_gameSys->fillSurface(0, _s49_scoreBarPos, 508, amount, 22, 89, 0, 5); +		_s49_scoreBarPos -= amount; +		_s49_scoreLevel = 0; +	} +} + +void GnapEngine::scene49_refreshScoreBar() { +	if (_s49_scoreBarFlash) +		_gameSys->fillSurface(0, 226, 508, 330, 22, 255, 0, 0); +	else +		_gameSys->fillSurface(0, 226, 508, 330, 22, 89, 0, 5); +	_s49_scoreBarFlash = !_s49_scoreBarFlash; +} + +void GnapEngine::scene49_clearObstacle(int index) { +	_s49_obstacles[index].currSequenceId = 0; +	_s49_obstacles[index].closerSequenceId = 0; +	_s49_obstacles[index].passedSequenceId = 0; +	_s49_obstacles[index].splashSequenceId = 0; +	_s49_obstacles[index].collisionSequenceId = 0; +	_s49_obstacles[index].prevId = 0; +	_s49_obstacles[index].currId = 0; +	_s49_obstacles[index].laneNum = 0; +} + +void GnapEngine::scene49_run() { +	 +	bool animToggle6 = false; +	bool animToggle5 = false; +	bool animToggle4 = false; +	bool animToggle3 = false; +	bool streetAnimToggle = false; +	bool bgAnimToggle = false; + +	playSound(0xE2, 1); +	setSoundVolume(0xE2, 75); + +	hideCursor(); +	setGrabCursorSprite(-1); + +	_s49_scoreBarPos = 196; +	_s49_scoreLevel = 0; +	_s49_scoreBarFlash = false; + +	switch (getRandom(3)) { +	case 0: +		_s49_truckSequenceId = 0xAD; +		_s49_truckLaneNum = 1; +		break; +	case 1: +		_s49_truckSequenceId = 0xAE; +		_s49_truckLaneNum = 2; +		break; +	case 2: +		_s49_truckSequenceId = 0xAF; +		_s49_truckLaneNum = 3; +		break; +	} + +	int bgWidth1 = _gameSys->getSpriteWidthById(0x5E); +	int bgX1 = 600; + +	int bgWidth2 = _gameSys->getSpriteWidthById(0x5F); +	int bgX2 = 400; + +	int bgWidth3 = _gameSys->getSpriteWidthById(4); +	int bgX3 = 700; + +	int bgWidth4 = _gameSys->getSpriteWidthById(5); +	int bgX4 = 500; + +	int bgWidth5 = _gameSys->getSpriteWidthById(6); +	int bgX5 = 300; + +	int bgWidth6 = _gameSys->getSpriteWidthById(7); +	int bgX6 = 100; + +	_gameSys->setAnimation(0xC8, 251, 1); +	_gameSys->setAnimation(_s49_truckSequenceId, 256, 0); +	_gameSys->insertSequence(0xC9, 256, 0, 0, kSeqNone, 0, 600, 85); +	_gameSys->insertSequence(0xCA, 257, 0, 0, kSeqNone, 0, 400, 100); +	_gameSys->insertSequence(0xC4, 256, 0, 0, kSeqNone, 0, 700, 140); +	_gameSys->insertSequence(0xC5, 257, 0, 0, kSeqNone, 0, 500, 160); +	_gameSys->insertSequence(0xC6, 258, 0, 0, kSeqNone, 0, 300, 140); +	_gameSys->insertSequence(0xC7, 259, 0, 0, kSeqNone, 0, 100, 140); +	_gameSys->insertSequence(0xC8, 251, 0, 0, kSeqNone, 0, 0, -50); +	_gameSys->insertSequence(_s49_truckSequenceId, 256, 0, 0, kSeqNone, 0, 0, -50); + +	_timers[0] = 2; + +	for (int i = 0; i < 5; ++i) +		scene49_clearObstacle(i); + +	_s49_obstacleIndex = 0; + +	_timers[2] = getRandom(20) + 10; + +	_s49_truckId = 256; +	_timers[3] = 35; +	 +	while (!_sceneDone) { + +		if (_timers[0] == 0) { +			// Update background animations (clouds etc.) +			--bgX1; +			bgX2 -= 2; +			bgX3 -= 5; +			--bgX4; +			--bgX5; +			--bgX6; +			if (bgX1 <= -bgWidth1) +				bgX1 = 799; +			if (bgX2 <= -bgWidth2) +				bgX2 = 799; +			if (bgX3 <= -bgWidth3) +				bgX3 = 799; +			if (bgX4 <= -bgWidth4) +				bgX4 = 799; +			if (bgX5 <= -bgWidth5) +				bgX5 = 799; +			if (bgX6 <= -bgWidth6) +				bgX6 = 799; +			bgAnimToggle = !bgAnimToggle; +			_gameSys->insertSequence(0xC9, (bgAnimToggle ? 1 : 0) + 256, 0xC9, (bgAnimToggle ? 0 : 1) + 256, kSeqSyncWait, 0, bgX1, 85); +			_gameSys->insertSequence(0xCA, (bgAnimToggle ? 1 : 0) + 257, 0xCA, (bgAnimToggle ? 0 : 1) + 257, kSeqSyncWait, 0, bgX2, 100); +			_gameSys->insertSequence(0xC4, (bgAnimToggle ? 1 : 0) + 256, 0xC4, (bgAnimToggle ? 0 : 1) + 256, kSeqSyncWait, 0, bgX3, 140); +			_gameSys->insertSequence(0xC5, (bgAnimToggle ? 1 : 0) + 257, 0xC5, (bgAnimToggle ? 0 : 1) + 257, kSeqSyncWait, 0, bgX4, 160); +			_gameSys->insertSequence(0xC6, (bgAnimToggle ? 1 : 0) + 258, 0xC6, (bgAnimToggle ? 0 : 1) + 258, kSeqSyncWait, 0, bgX5, 140); +			_gameSys->insertSequence(0xC7, (bgAnimToggle ? 1 : 0) + 259, 0xC7, (bgAnimToggle ? 0 : 1) + 259, kSeqSyncWait, 0, bgX6, 140); +			_timers[0] = 2; +		} + +		if (_gameSys->getAnimationStatus(1) == 2) { +			streetAnimToggle = !streetAnimToggle; +			_gameSys->setAnimation(0xC8, (streetAnimToggle ? 1 : 0) + 251, 1); +			_gameSys->insertSequence(0xC8, (streetAnimToggle ? 1 : 0) + 251, 200, (streetAnimToggle ? 0 : 1) + 251, kSeqSyncWait, 0, 0, -50); +		} + +		scene49_checkObstacles(); + +		if (_gameSys->getAnimationStatus(0) == 2) { +			switch (_s49_truckSequenceId) { +			case 0xB1: +				_s49_truckLaneNum = 1; +				break; +			case 0xB0: +			case 0xB3: +				_s49_truckLaneNum = 2; +				break; +			case 0xB2: +				_s49_truckLaneNum = 3; +				break; +			} +			animToggle3 = !animToggle3; +			if (_s49_truckLaneNum == 1) { +				_gameSys->setAnimation(0xAD, (animToggle3 ? 1 : 0) + 256, 0); +				_gameSys->insertSequence(0xAD, (animToggle3 ? 1 : 0) + 256, _s49_truckSequenceId, _s49_truckId, kSeqSyncWait, 0, 0, -50); +				_s49_truckSequenceId = 0xAD; +			} else if (_s49_truckLaneNum == 2) { +				_gameSys->setAnimation(0xAE, (animToggle3 ? 1 : 0) + 256, 0); +				_gameSys->insertSequence(0xAE, (animToggle3 ? 1 : 0) + 256, _s49_truckSequenceId, _s49_truckId, kSeqSyncWait, 0, 0, -50); +				_s49_truckSequenceId = 0xAE; +			} else { +				_gameSys->setAnimation(0xAF, (animToggle3 ? 1 : 0) + 256, 0); +				_gameSys->insertSequence(0xAF, (animToggle3 ? 1 : 0) + 256, _s49_truckSequenceId, _s49_truckId, kSeqSyncWait, 0, 0, -50); +				_s49_truckSequenceId = 0xAF; +			} +			_s49_truckId = (animToggle3 ? 1 : 0) + 256; +			if (_s49_scoreLevel == 1) { +				if (!_gameSys->isSequenceActive(0xD4, 266)) { +					_gameSys->setAnimation(0xD4, 266, 8); +					_gameSys->insertSequence(0xD4, 266, 0, 0, kSeqNone, 0, 0, -50); +				} +				++_s49_scoreLevel; +				_timers[1] = 2; +				animToggle4 = false; +				animToggle5 = false; +				animToggle6 = false; +				_s49_scoreBarFlash = false; +			} +		} + +		if (_s49_scoreLevel != 0 && !_timers[1]) { +			scene49_refreshScoreBar(); +			_timers[1] = 8; +			if (animToggle6) { +				if (animToggle5) { +					if (animToggle4 && !_gameSys->isSequenceActive(212, 266)) +						_gameSys->insertSequence(212, 266, 0, 0, kSeqNone, 0, 0, -50); +					animToggle4 = !animToggle4; +				} +				animToggle5 = !animToggle5; +			} +			animToggle6 = !animToggle6; +		} + +		scene49_updateAnimations(); + +		if (sceneXX_sub_4466B1()) { +			_sceneDone = true; +			_newSceneNum = 2; +			_newCursorValue = 1; +		} + +		if (isKeyStatus1(Common::KEYCODE_RIGHT)) { +			// Steer right +			if (_s49_truckSequenceId == 0xB3) +				_s49_truckLaneNum = 2; +			if (_s49_truckSequenceId == 0xB1) +				_s49_truckLaneNum = 1; +			if (_s49_truckLaneNum != 3 && _s49_truckLaneNum != 2) { +				if (_s49_scoreLevel) { +					_sceneDone = true; +					_newSceneNum = 47; +				} +			} else { +				int steerSequenceId = (_s49_truckLaneNum == 3) ? 0xB3 : 0xB1; +				if (_s49_truckSequenceId == 0xAE || _s49_truckSequenceId == 0xAF) { +					_gameSys->setAnimation(steerSequenceId, 256, 0); +					_gameSys->insertSequence(steerSequenceId, 256, _s49_truckSequenceId, _s49_truckId, 32, 0, 0, -50); +					_s49_truckSequenceId = steerSequenceId; +					_s49_truckId = 256; +				} +			} +			clearKeyStatus1(Common::KEYCODE_RIGHT); +		} + +		if (isKeyStatus1(Common::KEYCODE_LEFT)) { +			// Steer left +			if (_s49_truckSequenceId == 0xB0) +				_s49_truckLaneNum = 2; +			if (_s49_truckSequenceId == 0xB2) +				_s49_truckLaneNum = 3; +			if (_s49_truckLaneNum == 1 || _s49_truckLaneNum == 2) { +				int steerSequenceId = (_s49_truckLaneNum == 1) ? 0xB0 : 0xB2; +				if (_s49_truckSequenceId == 0xAD || _s49_truckSequenceId == 0xAE) { +					_gameSys->setAnimation(steerSequenceId, 256, 0); +					_gameSys->insertSequence(steerSequenceId, 256, _s49_truckSequenceId, _s49_truckId, 32, 0, 0, -50); +					_s49_truckSequenceId = steerSequenceId; +					_s49_truckId = 256; +				} +			} +			clearKeyStatus1(Common::KEYCODE_LEFT); +		} + +		gameUpdateTick(); + +	} + +	stopSound(0xE2); +   +} + +void GnapEngine::scene49_updateAnimations() { +	 +	for (int i = 0; i < 5; ++i) { +		if (_gameSys->getAnimationStatus(i + 2) == 2) { +			if (_s49_obstacles[i].currSequenceId) +				scene49_updateObstacle(i); +		} +	} + +	if (_gameSys->getAnimationStatus(8) == 2) { +		_sceneDone = true; +		_newSceneNum = 47; +	} +	 +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene50.cpp b/engines/gnap/scenes/scene50.cpp new file mode 100644 index 0000000000..ce24354be0 --- /dev/null +++ b/engines/gnap/scenes/scene50.cpp @@ -0,0 +1,479 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +int GnapEngine::scene50_init() { +	return 0xC7; +} + +void GnapEngine::scene50_updateHotspots() { +	_hotspotsCount = 0; +} + +bool GnapEngine::scene50_tongueWinsRound(int tongueNum) { +	if (tongueNum == 1) +		++_s50_leftTongueRoundsWon; +	else +		++_s50_rightTongueRoundsWon; +	scene50_playWinBadgeAnim(tongueNum); +	bool fightOver = _s50_rightTongueRoundsWon == 2 || _s50_leftTongueRoundsWon == 2; +	scene50_playWinAnim(tongueNum, fightOver); +	return fightOver; +} + +void GnapEngine::scene50_playWinAnim(int tongueNum, bool fightOver) { +	if (tongueNum == 1) { +		if (fightOver) { +			_gameSys->insertSequence(0xAD, 140, 0xAC, 140, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0xB4, 100, _s50_leftTongueSequenceId, _s50_leftTongueId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0xBD, 100, _s50_rightTongueSequenceId, _s50_rightTongueId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0xBC, 100, 0xBD, 100, kSeqSyncWait, 0, 0, 0); +			_s50_leftTongueSequenceId = 0xB4; +			_s50_rightTongueSequenceId = 0xBC; +			_s50_rightTongueId = 100; +			_s50_leftTongueId = 100; +			_gameSys->setAnimation(0xB4, 100, 6); +			_gameSys->setAnimation(_s50_rightTongueSequenceId, 100, 5); +			scene50_waitForAnim(6); +			scene50_waitForAnim(5); +			invAdd(kItemGum); +			setFlag(13); +		} else { +			_gameSys->insertSequence(0xB4, 100, _s50_leftTongueSequenceId, _s50_leftTongueId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0xBD, 100, _s50_rightTongueSequenceId, _s50_rightTongueId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0xBC, 100, 0xBD, 100, kSeqSyncWait, 0, 0, 0); +			_s50_leftTongueSequenceId = 0xB4; +			_s50_rightTongueSequenceId = 0xBC; +			_s50_rightTongueId = 100; +			_s50_leftTongueId = 100; +			_gameSys->setAnimation(0xB4, 100, 6); +			_gameSys->setAnimation(_s50_rightTongueSequenceId, 100, 5); +			scene50_waitForAnim(6); +			scene50_waitForAnim(5); +		} +	} else { +		_gameSys->insertSequence(0xBE, 100, _s50_rightTongueSequenceId, _s50_rightTongueId, kSeqSyncWait, 0, 0, 0); +		_gameSys->setAnimation(0xBE, 100, 5); +		scene50_waitForAnim(5); +		_gameSys->insertSequence(0xBF, 100, 0xBE, 100, kSeqSyncWait, 0, 0, 0); +		_gameSys->insertSequence(0xB5, 100, _s50_leftTongueSequenceId, _s50_leftTongueId, kSeqSyncWait, 0, 0, 0); +		_s50_rightTongueSequenceId = 0xBF; +		_s50_leftTongueSequenceId = 0xB5; +		_s50_rightTongueId = 100; +		_s50_leftTongueId = 100; +		_gameSys->setAnimation(0xB5, 100, 6); +		_gameSys->setAnimation(_s50_rightTongueSequenceId, 100, 5); +		scene50_waitForAnim(6); +		scene50_waitForAnim(5); +	} +	// TODO delayTicksA(1, 7); +} + +void GnapEngine::scene50_delayTicks() { +	// TODO delayTicksA(3, 7); +} + +void GnapEngine::scene50_initRound() { +	_s50_leftTongueEnergy = 10; +	_s50_rightTongueEnergy = 10; +	_s50_fightDone = false; +	_timers[3] = scene50_getRightTongueActionTicks(); +	_timers[4] = 0; +	_timers[6] = 0; +	_gameSys->fillSurface(0, 91, 73, 260, 30, 212, 0, 0); +	_gameSys->fillSurface(0, 450, 73, 260, 30, 212, 0, 0); +	_s50_timeRemaining = 40; +	scene50_drawCountdown(40); +} + +bool GnapEngine::scene50_updateCountdown() { +	if (!_timers[5]) { +		--_s50_timeRemaining; +		if (_s50_timeRemaining < 0) { +			return true; +		} else { +			_timers[5] = 15; +			scene50_drawCountdown(_s50_timeRemaining); +		} +	} +	return false; +} + +void GnapEngine::scene50_drawCountdown(int value) { +	char str[8]; +	sprintf(str, "%02d", value); +	_gameSys->fillSurface(0, 371, 505, 50, 27, 0, 0, 0); +	_gameSys->drawTextToSurface(0, 381, 504, 255, 255, 255, str); +} + +void GnapEngine::scene50_playTonguesIdle() { +	_gameSys->insertSequence(0xBA, 100, _s50_leftTongueSequenceId, _s50_leftTongueId, kSeqSyncWait, 0, 0, 0); +	_gameSys->insertSequence(0xC2, 100, _s50_rightTongueSequenceId, _s50_rightTongueId, kSeqSyncWait, 0, 0, 0); +	_s50_leftTongueSequenceId = 0xBA; +	_s50_rightTongueSequenceId = 0xC2; +	_s50_rightTongueNextSequenceId = -1; +	_s50_leftTongueNextSequenceId = -1; +	_s50_leftTongueId = 100; +	_s50_rightTongueId = 100; +	_gameSys->setAnimation(0xC2, 100, 5); +	_gameSys->setAnimation(_s50_leftTongueSequenceId, _s50_leftTongueId, 6); +} + +void GnapEngine::scene50_playRoundAnim(int roundNum) { +	int sequenceId; +	 +	switch (roundNum) { +	case 1: +		sequenceId = 0xAF; +		break; +	case 2: +		sequenceId = 0xB0; +		break; +	case 3: +		sequenceId = 0xB1; +		break; +	} + +	_gameSys->insertSequence(sequenceId, 256, 0, 0, kSeqNone, 0, 0, 0); +	_gameSys->setAnimation(sequenceId, 256, 7); +	scene50_waitForAnim(7); + +	_gameSys->insertSequence(0xAB, 256, sequenceId, 256, kSeqSyncWait, 0, 0, 0); +	_gameSys->setAnimation(0xAB, 256, 7); +	scene50_waitForAnim(7); + +} + +bool GnapEngine::scene50_updateEnergyBars(int newLeftBarPos, int newRightBarPos) { +	 +	if (newLeftBarPos != _s50_leftTongueEnergyBarPos) { +		if (newLeftBarPos < 0) +			newLeftBarPos = 0; +		_s50_leftTongueEnergyBarPos = newLeftBarPos; +		_gameSys->fillSurface(0, 26 * newLeftBarPos + 91, 73, 260 - 26 * newLeftBarPos, 30, 0, 0, 0); +	} + +	if (newRightBarPos != _s50_rightTongueEnergyBarPos) { +		if (newRightBarPos < 0) +			newRightBarPos = 0; +		_s50_rightTongueEnergyBarPos = newRightBarPos; +		if (newRightBarPos != 10) +			_gameSys->fillSurface(0, 26 * (9 - newRightBarPos) + 450, 73, 26, 30, 0, 0, 0); +	} + +	if (newLeftBarPos * newRightBarPos > 0) +		return false; + +	_s50_leftTongueEnergyBarPos = 10; +	_s50_rightTongueEnergyBarPos = 10; +	return true; +} + +void GnapEngine::scene50_waitForAnim(int animationIndex) { +	while (_gameSys->getAnimationStatus(animationIndex) != 2) { +		gameUpdateTick(); +	} +	_gameSys->setAnimation(0, 0, animationIndex); +} + +int GnapEngine::scene50_checkInput() { +	int sequenceId = -1; + +	if (isKeyStatus1(Common::KEYCODE_RIGHT)) { +		clearKeyStatus1(Common::KEYCODE_RIGHT); +		sequenceId = 0xB6; +	} else if (isKeyStatus1(Common::KEYCODE_LEFT)) { +		clearKeyStatus1(Common::KEYCODE_LEFT); +		sequenceId = 0xB3; +	} else if (isKeyStatus1(Common::KEYCODE_ESCAPE)) { +		clearKeyStatus1(Common::KEYCODE_ESCAPE); +		_s50_fightDone = true; +	} +	 +	return sequenceId; +} + +int GnapEngine::scene50_getRightTongueAction() { +	int sequenceId = -1; + +	if (!_timers[3]) { +		_timers[3] = scene50_getRightTongueActionTicks(); +		if (_s50_rightTongueEnergy >= _s50_leftTongueEnergy) { +			switch (getRandom(5)) { +			case 0: +				sequenceId = 0xBE; +				break; +			case 1: +				sequenceId = 0xBE; +				break; +			case 2: +				sequenceId = 0xBB; +				break; +			case 3: +				sequenceId = 0xBB; +				break; +			case 4: +				sequenceId = 0xBB; +				break; +			} +		} else { +			switch (getRandom(4)) { +			case 0: +				sequenceId = 0xBE; +				break; +			case 1: +				sequenceId = 0xBB; +				break; +			case 2: +				sequenceId = 0xBE; +				break; +			case 3: +				sequenceId = 0xBE; +				break; +			} +		} +	} + +	return sequenceId; +} + +void GnapEngine::scene50_updateAnimations() { +	 +	if (!_timers[4]) +		_s50_attackCounter = 0; + +	if (_gameSys->getAnimationStatus(5) == 2) { +		if (_s50_rightTongueSequenceId == 0xBE) { +			if (_s50_leftTongueSequenceId != 0xB3 && _s50_leftTongueSequenceId != 0xB8) +				_s50_rightTongueNextSequenceId = 0xBF; +			else +				_s50_rightTongueNextSequenceId = 0xC0; +		} +		if (_s50_rightTongueNextSequenceId == -1) +			_s50_rightTongueNextSequenceId = 0xC2; +		if (_s50_rightTongueNextSequenceId == 0xBF) { +			_s50_leftTongueNextId = scene50_getLeftTongueNextId(); +			_s50_rightTongueNextId = scene50_getRightTongueNextId(); +			_gameSys->setAnimation(_s50_rightTongueNextSequenceId, _s50_rightTongueNextId, 5); +			_gameSys->setAnimation(0xB9, _s50_leftTongueNextId, 6); +			_gameSys->insertSequence(_s50_rightTongueNextSequenceId, _s50_rightTongueNextId, _s50_rightTongueSequenceId, _s50_rightTongueId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0xB9, _s50_leftTongueNextId, _s50_leftTongueSequenceId, _s50_leftTongueId, 32, 0, 0, 0); +			_s50_rightTongueSequenceId = _s50_rightTongueNextSequenceId; +			_s50_rightTongueNextSequenceId = -1; +			_s50_leftTongueSequenceId = 0xB9; +			_s50_leftTongueNextSequenceId = -1; +			_s50_rightTongueId = _s50_rightTongueNextId; +			_s50_leftTongueId = _s50_leftTongueNextId; +			_s50_leftTongueEnergy -= getRandom(2) + 1;//CHECKME +		} else { +			_s50_rightTongueNextId = scene50_getRightTongueNextId(); +			_gameSys->setAnimation(_s50_rightTongueNextSequenceId, _s50_rightTongueNextId, 5); +			_gameSys->insertSequence(_s50_rightTongueNextSequenceId, _s50_rightTongueNextId, _s50_rightTongueSequenceId, _s50_rightTongueId, kSeqSyncWait, 0, 0, 0); +			_s50_rightTongueSequenceId = _s50_rightTongueNextSequenceId; +			_s50_rightTongueNextSequenceId = -1; +			_s50_rightTongueId = _s50_rightTongueNextId; +		} +	} + +	if (_gameSys->getAnimationStatus(6) == 2) { +		if (_s50_leftTongueSequenceId == 0xB6) { +			++_s50_attackCounter; +			if (_s50_timesPlayedModifier + 3 <= _s50_attackCounter) { +				_s50_leftTongueNextSequenceId = 0xB8; +			} else { +				_timers[4] = 20; +				//CHECKME +				if (_s50_rightTongueSequenceId != 0xBB && _s50_rightTongueSequenceId != 0xC0 && getRandom(8) != _s50_roundNum) +					_s50_leftTongueNextSequenceId = 0xB7; +				else +					_s50_leftTongueNextSequenceId = 0xB8; +			} +		} +		if (_s50_leftTongueNextSequenceId == 0xB3) +			--_s50_attackCounter; +		if (_s50_leftTongueNextSequenceId == -1) +			_s50_leftTongueNextSequenceId = 0xBA; +		if (_s50_leftTongueNextSequenceId == 0xB7) { +			_s50_leftTongueNextId = scene50_getLeftTongueNextId(); +			_s50_rightTongueNextId = scene50_getRightTongueNextId(); +			_gameSys->setAnimation(_s50_leftTongueNextSequenceId, _s50_leftTongueNextId, 6); +			_gameSys->setAnimation(0xC1, _s50_rightTongueNextId, 5); +			_gameSys->insertSequence(_s50_leftTongueNextSequenceId, _s50_leftTongueNextId, _s50_leftTongueSequenceId, _s50_leftTongueId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0xC1, _s50_rightTongueNextId, _s50_rightTongueSequenceId, _s50_rightTongueId, 32, 0, 0, 0); +			_s50_leftTongueSequenceId = _s50_leftTongueNextSequenceId; +			_s50_leftTongueNextSequenceId = -1; +			_s50_rightTongueSequenceId = 0xC1; +			_s50_rightTongueNextSequenceId = -1; +			_s50_rightTongueId = _s50_rightTongueNextId; +			_s50_leftTongueId = _s50_leftTongueNextId; +			--_s50_rightTongueEnergy; +		} else if (_s50_leftTongueNextSequenceId != 0xB8 || _s50_rightTongueSequenceId != 0xC2) { +			_s50_leftTongueNextId = scene50_getLeftTongueNextId(); +			_gameSys->setAnimation(_s50_leftTongueNextSequenceId, _s50_leftTongueNextId, 6); +			_gameSys->insertSequence(_s50_leftTongueNextSequenceId, _s50_leftTongueNextId, _s50_leftTongueSequenceId, _s50_leftTongueId, kSeqSyncWait, 0, 0, 0); +			_s50_leftTongueSequenceId = _s50_leftTongueNextSequenceId; +			_s50_leftTongueNextSequenceId = -1; +			_s50_leftTongueId = _s50_leftTongueNextId; +		} else { +			_s50_leftTongueNextId = scene50_getLeftTongueNextId(); +			_s50_rightTongueNextId = scene50_getRightTongueNextId(); +			_gameSys->setAnimation(0xBB, _s50_rightTongueNextId, 5); +			_gameSys->setAnimation(_s50_leftTongueNextSequenceId, _s50_leftTongueNextId, 6); +			_gameSys->insertSequence(_s50_leftTongueNextSequenceId, _s50_leftTongueNextId, _s50_leftTongueSequenceId, _s50_leftTongueId, kSeqSyncWait, 0, 0, 0); +			_gameSys->insertSequence(0xBB, _s50_rightTongueNextId, _s50_rightTongueSequenceId, _s50_rightTongueId, 32, 0, 0, 0); +			_s50_rightTongueSequenceId = 0xBB; +			_s50_rightTongueId = _s50_rightTongueNextId; +			_s50_rightTongueNextSequenceId = -1; +			_s50_leftTongueSequenceId = _s50_leftTongueNextSequenceId; +			_s50_leftTongueNextSequenceId = -1; +			_s50_leftTongueId = _s50_leftTongueNextId; +		} +	} + +} + +int GnapEngine::scene50_getRightTongueActionTicks() { +	return 15 - 5 * _s50_roundNum + 1; +} + +int GnapEngine::scene50_getLeftTongueNextId() { +	_s50_leftTongueNextIdCtr = (_s50_leftTongueNextIdCtr + 1) % 3; +	return _s50_leftTongueNextIdCtr + 100; +} + +int GnapEngine::scene50_getRightTongueNextId() { +	_s50_rightTongueNextIdCtr = (_s50_rightTongueNextIdCtr + 1) % 3; +	return _s50_rightTongueNextIdCtr + 100; +} + +void GnapEngine::scene50_playWinBadgeAnim(int tongueNum) { +	int sequenceId; +	 +	if (tongueNum == 1) { +		if (_s50_leftTongueRoundsWon == 1) +	  		sequenceId = 0xC3; +		else +	  		sequenceId = 0xC4; +	} else { +		if (_s50_rightTongueRoundsWon == 1) +			sequenceId = 0xC5; +		else +			sequenceId = 0xC6; +	} + +	_gameSys->setAnimation(sequenceId, 120, 7); +	_gameSys->insertSequence(sequenceId, 120, 0, 0, kSeqNone, 0, 0, 0); +	scene50_waitForAnim(7); + +} + +void GnapEngine::scene50_run() { +	 +	++_s50_timesPlayed; +	_s50_timesPlayedModifier = _s50_timesPlayed / 4; +	_s50_leftTongueRoundsWon = 0; +	_s50_rightTongueRoundsWon = 0; +	// scene50_initFont(); +	_s50_leftTongueSequenceId = 186; +	_s50_rightTongueSequenceId = 194; +	_s50_rightTongueNextSequenceId = -1; +	_s50_leftTongueNextSequenceId = -1; +	_s50_leftTongueId = 100; +	_s50_rightTongueId = 100; + +	_gameSys->setAnimation(194, 100, 5); +	_gameSys->setAnimation(_s50_leftTongueSequenceId, _s50_leftTongueId, 6); +	_gameSys->insertSequence(_s50_leftTongueSequenceId, _s50_leftTongueId, 0, 0, kSeqNone, 0, 0, 0); +	_gameSys->insertSequence(_s50_rightTongueSequenceId, _s50_rightTongueId, 0, 0, kSeqNone, 0, 0, 0); +	_gameSys->insertSequence(172, 140, 0, 0, kSeqNone, 0, 0, 0); +	endSceneInit(); + +	scene50_initRound(); + +	_s50_roundNum = 1; + +	setGrabCursorSprite(-1); +	hideCursor(); + +	// TODO delayTicksA(1, 7); + +	scene50_playRoundAnim(_s50_roundNum); + +	_timers[5] = 15; + +	while (!_s50_fightDone) { + +		/* TODO +		if (sceneXX_sub_4466B1()) +			_s50_fightDone = true; +		*/ + +		int playerSequenceId = scene50_checkInput(); +		if (playerSequenceId != -1) +			_s50_leftTongueNextSequenceId = playerSequenceId; + +		int rightSequenceId = scene50_getRightTongueAction(); +		if (rightSequenceId != -1) +			_s50_rightTongueNextSequenceId = rightSequenceId; + +		scene50_updateAnimations(); + +		if (scene50_updateCountdown() || +			scene50_updateEnergyBars(_s50_leftTongueEnergy, _s50_rightTongueEnergy)) { +			int v0; +			if (_s50_rightTongueEnergy < _s50_leftTongueEnergy) +				v0 = scene50_tongueWinsRound(1); +			else +				v0 = scene50_tongueWinsRound(2); +			if (v0) { +				scene50_delayTicks(); +				_s50_fightDone = true; +			} else { +				++_s50_roundNum; +				scene50_initRound(); +				scene50_playTonguesIdle(); +				scene50_updateEnergyBars(_s50_leftTongueEnergy, _s50_rightTongueEnergy); +				scene50_playRoundAnim(_s50_roundNum); +				_timers[5] = 15; +			} +		} +		 +		gameUpdateTick(); + +	} + +	// scene50_freeFont(); +	 +	_gameSys->setAnimation(0, 0, 7); +	_gameSys->setAnimation(0, 0, 6); +	_gameSys->setAnimation(0, 0, 5); +	_gameSys->setAnimation(0, 0, 3); + +	showCursor(); +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene51.cpp b/engines/gnap/scenes/scene51.cpp new file mode 100644 index 0000000000..1313c1d2db --- /dev/null +++ b/engines/gnap/scenes/scene51.cpp @@ -0,0 +1,880 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +static const int kDigitSequenceIds[] = { +	0xCA, 0xCB, 0xCC, 0xCD, 0xCE, +	0xCF, 0xD0, 0xD1, 0xD2, 0xD3 +}; + +static const int kDigitPositions[4] = { +	0, 34, 83, 119 +}; + +/* +	0xBA	Falling banana peel +	0xBC	Banana peel goes away +	0xBD	Falling coin +	0xBE	Fallen coin +	0xC0	Falling banknote +	0xB6	Platypus tripping (right) +	0xB7	Platypus tripping (left) +	0x76	Platypus jumping (right) +*/ + +int GnapEngine::scene51_init() { +	_gameSys->setAnimation(0, 0, 0); +	for (int i = 0; i < 6; ++i) +		_gameSys->setAnimation(0, 0, i + 1); +	return 0xD4; +} + +void GnapEngine::scene51_updateHotspots() { +	_hotspotsCount = 0; +} + +void GnapEngine::scene51_clearItem(Scene51Item *item) { +	item->currSequenceId = 0; +	item->droppedSequenceId = 0; +	item->x = 0; +	item->y = 0; +	item->x2 = 0; +	item->collisionX = 0; +	item->canCatch = 0; +} + +void GnapEngine::scene51_dropNextItem() { + +	if (_timers[0]) +		return; + +	int index = 0; + +	while (index < 6 && _s51_items[index].currSequenceId) +		++index; + +	if (index == 6) +		return; + +	switch (_s51_nextDropItemKind) { + +	case 0: +		if (getRandom(10) != 0 || _s51_itemsCtr2 >= 2) { +			_s51_items[index].currSequenceId = 0xBD; +		} else { +			--_s51_itemsCtr1; +			_s51_items[index].currSequenceId = 0xBA; +			++_s51_itemsCtr2; +		} +		break; + +	case 1: +		if (getRandom(8) != 0 || _s51_itemsCtr2 >= 2) { +			if (getRandom(5) == 0) { +				if (_s51_itemInsertDirection) +					_s51_itemInsertX -= 70; +				else +					_s51_itemInsertX += 70; +			} +			_s51_items[index].currSequenceId = 0xBD; +		} else { +			--_s51_itemsCtr1; +			_s51_items[index].currSequenceId = 0xBA; +			++_s51_itemsCtr2; +		} +		break; + +	case 2: +		if (getRandom(6) != 0 || _s51_itemsCtr2 >= 2) { +			_s51_items[index].currSequenceId = 0xBD; +		} else { +			--_s51_itemsCtr1; +			_s51_items[index].currSequenceId = 0xBA; +			++_s51_itemsCtr2; +		} +		break; + +	case 3: +	case 4: +		if (_s51_itemsCtr == 0) +			_s51_itemsCtr1 = 3; +		_s51_items[index].currSequenceId = 0xC0; +		break; + +	case 5: +	case 6: +		if (getRandom(5) != 0 || _s51_itemsCtr2 >= 2) { +			if (getRandom(5) != 0) +				_s51_items[index].currSequenceId = 0xBD; +			else +				_s51_items[index].currSequenceId = 0xC0; +		} else { +			--_s51_itemsCtr1; +			_s51_items[index].currSequenceId = 0xBA; +			++_s51_itemsCtr2; +		} +		break; + +	case 7: +		if (getRandom(5) != 0 || _s51_itemsCtr2 >= 2) { +			if (getRandom(5) == 0) { +				if (_s51_itemInsertDirection) +					_s51_itemInsertX -= 40; +				else +					_s51_itemInsertX += 40; +			} +			if (getRandom(9) != 0) +				_s51_items[index].currSequenceId = 0xBD; +			else +				_s51_items[index].currSequenceId = 0xC0; +		} else { +			--_s51_itemsCtr1; +			_s51_items[index].currSequenceId = 0xBA; +			++_s51_itemsCtr2; +		} +		break; + +	default: +		if (getRandom(4) != 0 || _s51_itemsCtr2 >= 2) { +			if (getRandom(9) != 0) +				_s51_items[index].currSequenceId = 0xBD; +			else +				_s51_items[index].currSequenceId = 0xC0; +		} else { +			--_s51_itemsCtr1; +			_s51_items[index].currSequenceId = 0xBA; +			++_s51_itemsCtr2; +		} +		break; + +	} + +	if (_s51_itemInsertDirection) { +		_s51_itemInsertX -= 73; +		if (_s51_itemInsertX < 129) { +			_s51_itemInsertX += 146; +			_s51_itemInsertDirection = 0; +		} +	} else { +		_s51_itemInsertX += 73; +		if (_s51_itemInsertX > 685) { +			_s51_itemInsertX -= 146; +			_s51_itemInsertDirection = 1; +		} +	} + +	if (_s51_itemInsertX > 685) +		_s51_itemInsertX = 685; + +	if (_s51_itemInsertX < 129) +		_s51_itemInsertX = 129; + +	if (_s51_items[index].currSequenceId == 0xBA) { +		_s51_items[index].x2 = getRandom(350) + 200; +		_s51_items[index].x = _s51_items[index].x2 - 362; +		_s51_items[index].y = 15; +		_s51_items[index].id = 249 - index; +	} else { +		_s51_items[index].collisionX = _s51_itemInsertX; +		_s51_items[index].x = _s51_items[index].collisionX - 395; +		if (_s51_items[index].currSequenceId == 0xC0) +			_s51_items[index].x -= 65; +		_s51_items[index].id = index + 250; +		_s51_items[index].canCatch = 1; +	} + +	_gameSys->setAnimation(_s51_items[index].currSequenceId, _s51_items[index].id, index + 1); +	_gameSys->insertSequence(_s51_items[index].currSequenceId, _s51_items[index].id, 0, 0, +		kSeqNone, 0, _s51_items[index].x, _s51_items[index].y); + +	_timers[0] = _s51_dropSpeedTicks; + +	if (_s51_nextDropItemKind >= 3) +		_timers[0] = 20; + +	if (_s51_nextDropItemKind >= 5) +		_timers[0] = 5; + +	if (_s51_nextDropItemKind == 8) +		_timers[0] = 4; + +	++_s51_itemsCtr; + +} + +void GnapEngine::scene51_updateItemAnimations() { +	for (int i = 0; i < 6; ++i) +		if (_gameSys->getAnimationStatus(i + 1) == 2) +			scene51_updateItemAnimation(&_s51_items[i], i); +} + +int GnapEngine::scene51_checkCollision(int sequenceId) { +	bool jumpingLeft = false, jumpingRight = false; +	int v6 = 0; +	int v2 = 0; +	int v5 = 0; +	int v8, v4; +	int result = 0; + +	if (!scene51_isJumping(sequenceId)) +		return false; + +	while (v6 < 6) +		v2 += _s51_items[v6++].isCollision; +		 +	if (!v2) +		return false; +		 +	if (scene51_isJumpingRight(sequenceId)) { +		v8 = scene51_getPosRight(sequenceId); +		v4 = scene51_getPosRight(sequenceId + 1); +		jumpingRight = true; +	} else if (scene51_isJumpingLeft(sequenceId)) { +		v4 = scene51_getPosLeft(sequenceId - 1) + 33; +		v8 = scene51_getPosLeft(sequenceId) + 33; +		jumpingLeft = true; +	} + +	if (jumpingRight || jumpingLeft) { +		int i; +		for (i = 0; i < 6; ++i) { +			if (_s51_items[i].isCollision) { +				if (jumpingRight && _s51_items[i].x2 > v8 && _s51_items[i].x2 < v4) { +					v5 = v8 - 359; +					if (v8 == 359) +						v5 = 1; +					_s51_platypusNextSequenceId = 0xB6; +					break; +				} else if (jumpingLeft && _s51_items[i].x2 < v4 && _s51_items[i].x2 > v8) { +					v5 = v8 - 344; +					if (v8 == 344) +						v5 = 1; +					_s51_platypusNextSequenceId = 0xB7; +					break; +				} +			} +		} +		if (v5) { +			_gameSys->setAnimation(0xBC, _s51_items[i].id, i + 1); +			_gameSys->insertSequence(0xBC, _s51_items[i].id, _s51_items[i].currSequenceId, _s51_items[i].id, kSeqSyncWait, 0, _s51_items[i].x, 15); +			_s51_items[i].isCollision = 0; +			_s51_items[i].currSequenceId = 0xBC; +			--_s51_itemsCtr2; +		} +		result = v5; +	} + +	return result; +} + +void GnapEngine::scene51_updateItemAnimation(Scene51Item *item, int index) { + +	switch (item->currSequenceId) { + +	case 0xBD: +	case 0xC0: +	case 0xC1: +		// Falling coin and banknote +		if (!scene51_itemIsCaught(item)) { +			if (_s51_dropLoseCash) { +				if (item->currSequenceId == 0xBD) +					_s51_cashAmount -= 2; +				else +					_s51_cashAmount -= 25; +				if (_s51_cashAmount < 0) +					_s51_cashAmount = 0; +				scene51_updateCash(_s51_cashAmount); +			} +			item->droppedSequenceId = item->currSequenceId + 1; +			if (item->currSequenceId != 0xC0) { +				item->canCatch = 0; +				_s51_dropLoseCash = true; +				_s51_itemsCtr = 0; +				_timers[0] = 10; +			} +			if (item->droppedSequenceId) { +				_gameSys->setAnimation(item->droppedSequenceId, item->id, index + 1); +				_gameSys->insertSequence(item->droppedSequenceId, item->id, item->currSequenceId, item->id, kSeqSyncWait, 0, item->x, item->y); +				item->currSequenceId = item->droppedSequenceId; +				item->y = 0; +			} +		} else { +			_gameSys->removeSequence(item->currSequenceId, item->id, 1); +			_gameSys->setAnimation(0, 0, index + 1); +			playSound(218, 0); +			if (scene51_incCashAmount(item->currSequenceId) == 1995) { +				scene51_winMinigame(); +				_sceneDone = true; +			} else { +				scene51_clearItem(item); +				++_s51_itemsCaughtCtr; +				if (_s51_itemsCaughtCtr == 5) +					--_s51_dropSpeedTicks; +				if (_s51_itemsCaughtCtr == 8) +					--_s51_dropSpeedTicks; +				if (_s51_itemsCaughtCtr == 11) +					--_s51_dropSpeedTicks; +				if (_s51_itemsCaughtCtr == 14) +					--_s51_dropSpeedTicks; +				if (_s51_itemsCaughtCtr >= 15 && _s51_dropSpeedTicks > 4) +					--_s51_dropSpeedTicks; +				if (_s51_itemsCtr1 <= _s51_itemsCaughtCtr) { +					++_s51_nextDropItemKind; +					_s51_dropSpeedTicks = 10; +					_s51_itemsCtr = 0; +					_s51_itemsCtr1 = 20; +					_s51_dropLoseCash = false; +					_s51_itemsCaughtCtr = 0; +					scene51_removeCollidedItems(); +				} +			} +		} +		break; + +	case 0xBE: +		// Fallen coin +		item->droppedSequenceId = item->currSequenceId + 1; +		if (item->droppedSequenceId) { +			_gameSys->setAnimation(item->droppedSequenceId, item->id, index + 1); +			_gameSys->insertSequence(item->droppedSequenceId, item->id, item->currSequenceId, item->id, kSeqSyncWait, 0, item->x, item->y); +			item->currSequenceId = item->droppedSequenceId; +			item->y = 0; +		} +		break; + +	case 0xBF: +	case 0xC2: +		// Bouncing coin and banknote +		_gameSys->setAnimation(0, 0, index + 1); +		_gameSys->removeSequence(item->currSequenceId, item->id, 1); +		scene51_clearItem(item); +		break; + +	case 0xBA: +		// Falling banana peel +		item->droppedSequenceId = 0xBB; +		item->y = 15; +		if (item->droppedSequenceId) { +			_gameSys->setAnimation(item->droppedSequenceId, item->id, index + 1); +			_gameSys->insertSequence(item->droppedSequenceId, item->id, item->currSequenceId, item->id, kSeqSyncWait, 0, item->x, item->y); +			item->currSequenceId = item->droppedSequenceId; +			item->y = 0; +		} +		break; + +	case 0xBB: +		item->isCollision = 1; +		item->droppedSequenceId = 0; +		_gameSys->setAnimation(0, 0, index + 1); +		break; + +	case 0xBC: +		_gameSys->removeSequence(item->currSequenceId, item->id, 1); +		_gameSys->setAnimation(0, 0, index + 1); +		scene51_clearItem(item); +		break; + +	default: +		if (item->droppedSequenceId) { +			_gameSys->setAnimation(item->droppedSequenceId, item->id, index + 1); +			_gameSys->insertSequence(item->droppedSequenceId, item->id, item->currSequenceId, item->id, kSeqSyncWait, 0, item->x, item->y); +			item->currSequenceId = item->droppedSequenceId; +			item->y = 0; +		} +		break; + +	} + +} + +void GnapEngine::scene51_removeCollidedItems() { +	for (int i = 0; i < 6; ++i) { +		if (_s51_items[i].isCollision) { +			_gameSys->removeSequence(_s51_items[i].currSequenceId, _s51_items[i].id, 1); +			_gameSys->setAnimation(0, 0, i + 1); +			scene51_clearItem(&_s51_items[i]); +		} +	} +	_s51_itemsCtr2 = 0; +} + +int GnapEngine::scene51_itemIsCaught(Scene51Item *item) { +	 +	if (!item->canCatch) +		return 0; + +	if (scene51_isJumpingRight(_s51_platypusJumpSequenceId)) { +		int v4 = scene51_getPosRight(_s51_platypusJumpSequenceId) + 97; +		if (item->collisionX < v4 && v4 - item->collisionX < 56) +			return 1; +	} else { +		int v2 = scene51_getPosLeft(_s51_platypusJumpSequenceId); +		if (item->collisionX > v2 && item->collisionX - v2 < 56) +			return 1; +	} + +	if (item->currSequenceId == 0xC1) { +		int v3 = item->collisionX + 100; +		if (scene51_isJumpingRight(_s51_platypusJumpSequenceId)) { +			if (ABS(scene51_getPosRight(_s51_platypusJumpSequenceId) + 46 - v3) < 56) +				return 1; +		} else if (ABS(scene51_getPosLeft(_s51_platypusJumpSequenceId) + 46 - v3) < 56) { +			return 1; +		} +	} + +	return 0; +} + +bool GnapEngine::scene51_isJumpingRight(int sequenceId) { +	return sequenceId >= 0x76 && sequenceId <= 0x95; +} + +bool GnapEngine::scene51_isJumpingLeft(int sequenceId) { +	return sequenceId >= 0x96 && sequenceId <= 0xB5; +} + +bool GnapEngine::scene51_isJumping(int sequenceId) { +	return sequenceId >= 0x76 && sequenceId <= 0xB5; +} + +void GnapEngine::scene51_waitForAnim(int animationIndex) { +	while (_gameSys->getAnimationStatus(animationIndex) != 2) { +		// pollMessages(); +		scene51_updateItemAnimations(); +		gameUpdateTick(); +	} +} + +int GnapEngine::scene51_getPosRight(int sequenceId) { +	static const int kRightPosTbl[] = { +		131, 159, 178, 195, 203, 219, 238, 254, +		246, 274, 293, 310, 318, 334, 353, 369, +		362, 390, 409, 426, 434, 450, 469, 485, +		477, 505, 524, 541, 549, 565, 584, 600 +	}; + +	if (sequenceId >= 118 && sequenceId <= 149) +		return kRightPosTbl[sequenceId - 118]; +	return -1; +} + +int GnapEngine::scene51_getPosLeft(int sequenceId) { +	static const int kLeftPosTbl[] = { +		580, 566, 550, 536, 526, 504, 488, 469, +		460, 446, 430, 416, 406, 384, 368, 349, +		342, 328, 312, 298, 288, 266, 250, 231, +		220, 206, 190, 176, 166, 144, 128, 109 +	}; + +	if (sequenceId >= 150 && sequenceId <= 181) +		return kLeftPosTbl[sequenceId - 150]; +	return -1; +} + +void GnapEngine::scene51_playIntroAnim() { +	int soundCtr = 0; + +	_s51_platypusSequenceId = 0x76; +	_s51_platypusNextSequenceId = 0x76; + +	for (int i = 0; i < 6; ++i) +		scene51_clearItem(&_s51_items[i]); + +	_s51_items[0].currSequenceId = 0xBA; +	_s51_items[0].x2 = 320; +	_s51_items[0].x = -42; +	_s51_items[0].y = 15; +	_s51_items[0].id = 249; +	_s51_items[0].isCollision = 1; + +	_gameSys->insertSequence(_s51_platypusSequenceId, 256, 0, 0, kSeqNone, 0, -179, 0); +	_gameSys->insertSequence(0xBA, 249, 0, 0, kSeqNone, 0, _s51_items[0].x, _s51_items[0].y); +	_gameSys->setAnimation(0xBA, 249, 1); +	_gameSys->setAnimation(_s51_platypusSequenceId, 256, 0); + +	while (_s51_platypusSequenceId < 0x80) { +		scene51_waitForAnim(0); +		++_s51_platypusNextSequenceId; +		_gameSys->setAnimation(_s51_platypusNextSequenceId, 256, 0); +		_gameSys->insertSequence(_s51_platypusNextSequenceId, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, -179, 0); +		_s51_platypusSequenceId = _s51_platypusNextSequenceId; +		++soundCtr; +		if (soundCtr % 4 == 0) +			playSound(214, 0); +	} + +	_s51_platypusNextSequenceId = 0x75; + +	while (_s51_platypusSequenceId != 0x84) { +		scene51_waitForAnim(0); +		++_s51_platypusNextSequenceId; +		int oldSequenceId = _s51_platypusNextSequenceId; +		int v0 = scene51_checkCollision(_s51_platypusNextSequenceId); +		_gameSys->setAnimation(_s51_platypusNextSequenceId, 256, 0); +		_gameSys->insertSequence(_s51_platypusNextSequenceId, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, v0, 0); +		_s51_platypusSequenceId = _s51_platypusNextSequenceId; +		if (v0) { +			_s51_platypusNextSequenceId = oldSequenceId; +		} else { +			++soundCtr; +			if (soundCtr % 4 == 0) +				playSound(214, 0); +		} +	} + +	scene51_waitForAnim(0); + +} + +void GnapEngine::scene51_updateGuyAnimation() { +	 +	if (!_timers[4]) { +		_timers[4] = getRandom(20) + 60; + +		switch (getRandom(5)) { +		case 0: +			_s51_guyNextSequenceId = 0xC3; +			break; +		case 1: +			_s51_guyNextSequenceId = 0xC4; +			break; +		case 2: +			_s51_guyNextSequenceId = 0xC5; +			break; +		case 3: +			_s51_guyNextSequenceId = 0xC6; +			break; +		case 4: +			_s51_guyNextSequenceId = 0xC7; +			break; +		} +	 +		_gameSys->insertSequence(_s51_guyNextSequenceId, 39, _s51_guySequenceId, 39, kSeqSyncWait, 0, 0, 0); +		_s51_guySequenceId = _s51_guyNextSequenceId; +		_s51_guyNextSequenceId = -1; + +	} + +} + +int GnapEngine::scene51_incCashAmount(int sequenceId) { +	switch (sequenceId) { +	case 0xBD: +		_s51_cashAmount += 10; +		break; +	case 0xC0: +	case 0xC1: +		_s51_cashAmount += 100; +		break; +	case 0xB6: +	case 0xB7: +		_s51_cashAmount -= 10 * getRandom(5) + 50; +		if (_s51_cashAmount < 0) +			_s51_cashAmount = 0; +		break; +	} +	if (_s51_cashAmount > 1995) +		_s51_cashAmount = 1995; +	scene51_updateCash(_s51_cashAmount); +	return _s51_cashAmount; +} + +void GnapEngine::scene51_winMinigame() { +	scene51_updateCash(1995); +	playSound(218, 0); +	// TODO delayTicksA(1, 5); +	_newSceneNum = 48; +	invRemove(kItemBanana); +} + +void GnapEngine::scene51_playCashAppearAnim() { +	_gameSys->setAnimation(0xC8, 252, 0); +	_gameSys->insertSequence(0xC8, 252, 0, 0, kSeqNone, 0, -20, -20); +	while (_gameSys->getAnimationStatus(0) != 2) { +		gameUpdateTick(); +		// checkGameAppStatus(); +	} +} + +void GnapEngine::scene51_updateCash(int amount) { +	scene51_drawDigit(amount / 1000, 0); +	scene51_drawDigit(amount / 100 % 10, 1); +	scene51_drawDigit(amount / 10 % 10, 2); +	scene51_drawDigit(amount % 10, 3); +} + +void GnapEngine::scene51_drawDigit(int digit, int position) { +	if (digit != _s51_digits[position]) { +		_gameSys->insertSequence(kDigitSequenceIds[digit], 253, +			_s51_digitSequenceIds[position], 253, +			kSeqSyncWait, 0, kDigitPositions[position] - 20, -20); +		_s51_digitSequenceIds[position] = kDigitSequenceIds[digit]; +		_s51_digits[position] = digit; +	} +} + +void GnapEngine::scene51_initCashDisplay() { +	for (int position = 0; position < 4; ++position) { +		_s51_digits[position] = 0; +		_s51_digitSequenceIds[position] = kDigitSequenceIds[0]; +		_gameSys->insertSequence(kDigitSequenceIds[0], 253, 0, 0, +			kSeqNone, 0, kDigitPositions[position] - 20, -20); +	} +	_s51_cashAmount = 0; +} + +void GnapEngine::scene51_run() { +	 +	int soundCtr = 0; +	bool isIdle = true; + +	_s51_itemsCtr = 0; +	_newSceneNum = _prevSceneNum; +	_s51_cashAmount = 0; +	_s51_platypusJumpSequenceId = 0x84; +	endSceneInit(); + +	hideCursor(); +	setGrabCursorSprite(-1); + +	_s51_guySequenceId = 0xC3; +	_s51_guyNextSequenceId = -1; + +	_gameSys->insertSequence(0xC3, 39, 0, 0, kSeqNone, 0, 0, 0); + +	_timers[4] = getRandom(20) + 60; + +	scene51_playCashAppearAnim(); +	scene51_initCashDisplay(); +	scene51_playIntroAnim(); + +	_s51_platypusNextSequenceId = 0x74; +	_gameSys->setAnimation(0x74, 256, 0); +	_gameSys->insertSequence(_s51_platypusNextSequenceId, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, scene51_getPosRight(_s51_platypusJumpSequenceId) - 362, 0); +	_s51_platypusSequenceId = _s51_platypusNextSequenceId; + +	_s51_itemInsertDirection = 0; +	_s51_itemInsertX = 685; +	_s51_dropSpeedTicks = 10; +	_s51_nextDropItemKind = 0; + +	for (int i = 0; i < 6; ++i) +		scene51_clearItem(&_s51_items[i]); + +	_s51_itemInsertX = getRandom(556) + 129; + +	_timers[0] = 15; + +	_s51_itemsCaughtCtr = 0; +	_s51_dropLoseCash = false; +	_s51_itemsCtr1 = 20; + +	clearKeyStatus1(Common::KEYCODE_RIGHT); +	clearKeyStatus1(Common::KEYCODE_LEFT); +	clearKeyStatus1(Common::KEYCODE_UP); +	clearKeyStatus1(Common::KEYCODE_SPACE); +	clearKeyStatus1(Common::KEYCODE_ESCAPE); + +	bool isCollision = false; +	bool startWalk = true; + +	while (!_sceneDone) { + +		if (sceneXX_sub_4466B1()) +			_sceneDone = true; + +		gameUpdateTick(); + +		scene51_updateGuyAnimation(); +		scene51_dropNextItem(); +		scene51_updateItemAnimations(); + +		if (isKeyStatus2(Common::KEYCODE_UP) || isKeyStatus2(Common::KEYCODE_SPACE)) { +			clearKeyStatus1(Common::KEYCODE_UP); +			clearKeyStatus1(Common::KEYCODE_SPACE); +			if (scene51_isJumpingRight(_s51_platypusJumpSequenceId)) { +				scene51_waitForAnim(0); +				_gameSys->setAnimation(0xB8, 256, 0); +				_gameSys->insertSequence(0xB8, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, scene51_getPosRight(_s51_platypusJumpSequenceId) - 348, 0); +				_s51_platypusSequenceId = 0xB8; +				scene51_waitForAnim(0); +				_s51_platypusNextSequenceId += 6; +				if (_s51_platypusNextSequenceId > 0x95) +					_s51_platypusNextSequenceId = 0x95; +				_s51_platypusJumpSequenceId = _s51_platypusNextSequenceId; +			} else { +				scene51_waitForAnim(0); +				_gameSys->setAnimation(0xB9, 256, 0); +				_gameSys->insertSequence(0xB9, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, scene51_getPosLeft(_s51_platypusJumpSequenceId) - 338, 0); +				_s51_platypusSequenceId = 0xB9; +				scene51_waitForAnim(0); +				_s51_platypusNextSequenceId += 6; +				if (_s51_platypusNextSequenceId > 0xB5) +					_s51_platypusNextSequenceId = 0xB5; +				_s51_platypusJumpSequenceId = _s51_platypusNextSequenceId; +			} +			isIdle = false; +		} + +		while (isKeyStatus2(Common::KEYCODE_RIGHT) && _s51_platypusNextSequenceId != 0x96) { +			// pollMessages(); +			if (_s51_platypusNextSequenceId == 0xB6) +				_s51_platypusNextSequenceId = 0x76; +			scene51_updateItemAnimations(); +			if (startWalk) { +				_s51_platypusNextSequenceId = 0x86; +				startWalk = false; +			} + +			if (_gameSys->getAnimationStatus(0) == 2) { +				int collisionX = scene51_checkCollision(_s51_platypusNextSequenceId); +				if (collisionX) +					scene51_incCashAmount(_s51_platypusNextSequenceId); +				_gameSys->setAnimation(_s51_platypusNextSequenceId, 256, 0); +				_gameSys->insertSequence(_s51_platypusNextSequenceId, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, collisionX, 0); +				_s51_platypusSequenceId = _s51_platypusNextSequenceId; +				if (collisionX) { +					isCollision = true; +					++_s51_platypusJumpSequenceId; +					_s51_platypusNextSequenceId = _s51_platypusJumpSequenceId; +				} else { +					_s51_platypusJumpSequenceId = _s51_platypusNextSequenceId; +				} +				if (scene51_isJumpingRight(_s51_platypusJumpSequenceId)) { +					++_s51_platypusNextSequenceId; +					if (!isCollision) { +						if (isKeyStatus2(Common::KEYCODE_UP) || isKeyStatus2(Common::KEYCODE_SPACE)) { +							clearKeyStatus1(Common::KEYCODE_UP); +							clearKeyStatus1(Common::KEYCODE_SPACE); +							scene51_waitForAnim(0); +							_gameSys->setAnimation(0xB8, 256, 0); +							_gameSys->insertSequence(0xB8, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, scene51_getPosRight(_s51_platypusJumpSequenceId) - 348, 0); +							_s51_platypusSequenceId = 0xB8; +							scene51_waitForAnim(0); +							_s51_platypusNextSequenceId += 6; +							if (_s51_platypusNextSequenceId > 0x95) +								_s51_platypusNextSequenceId = 0x95; +							_s51_platypusJumpSequenceId = _s51_platypusNextSequenceId; +						} else { +							++soundCtr; +							if (soundCtr % 4 == 0) +								playSound(214, 0); +						} +					} +				} else { +					_s51_platypusNextSequenceId = 150 - (_s51_platypusJumpSequenceId - 150); +				} +				isCollision = false; +				isIdle = false; +			} +			gameUpdateTick(); +		} + +		while (isKeyStatus2(Common::KEYCODE_LEFT) && _s51_platypusNextSequenceId != 0xB6) { +			// pollMessages(); +			scene51_updateItemAnimations(); +			if (startWalk) { +				_s51_platypusNextSequenceId = 0xA5; +				startWalk = false; +			} + +			if (_gameSys->getAnimationStatus(0) == 2) { +				int collisionX = scene51_checkCollision(_s51_platypusNextSequenceId); +				if (collisionX) +					scene51_incCashAmount(_s51_platypusNextSequenceId); +				_gameSys->setAnimation(_s51_platypusNextSequenceId, 256, 0); +				_gameSys->insertSequence(_s51_platypusNextSequenceId, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, collisionX, 0); +				_s51_platypusSequenceId = _s51_platypusNextSequenceId; +				if (collisionX) { +					isCollision = true; +					++_s51_platypusJumpSequenceId; +					_s51_platypusNextSequenceId = _s51_platypusJumpSequenceId; +				} else { +					_s51_platypusJumpSequenceId = _s51_platypusNextSequenceId; +				} +				if (scene51_isJumpingLeft(_s51_platypusJumpSequenceId)) { +					++_s51_platypusNextSequenceId; +					if (!isCollision) { +						if (isKeyStatus2(Common::KEYCODE_UP) || isKeyStatus2(Common::KEYCODE_SPACE)) { +							clearKeyStatus1(Common::KEYCODE_UP); +							clearKeyStatus1(Common::KEYCODE_SPACE); +							scene51_waitForAnim(0); +							_gameSys->setAnimation(0xB9, 256, 0); +							_gameSys->insertSequence(0xB9, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, scene51_getPosLeft(_s51_platypusJumpSequenceId) - 338, 0); +							_s51_platypusSequenceId = 0xB9; +							scene51_waitForAnim(0); +							_s51_platypusNextSequenceId += 6; +							if (_s51_platypusNextSequenceId > 0xB5) +								_s51_platypusNextSequenceId = 0xB5; +							_s51_platypusJumpSequenceId = _s51_platypusNextSequenceId; +						} else { +							++soundCtr; +							if (soundCtr % 4 == 0) +								playSound(214, 0); +						} +					} +				} else { +					_s51_platypusNextSequenceId = 182 - (_s51_platypusJumpSequenceId - 118); +				} +				isCollision = false; +				isIdle = false; +			} +			gameUpdateTick(); +		} + +		if (!isIdle && _gameSys->getAnimationStatus(0) == 2) { +			if (scene51_isJumpingRight(_s51_platypusJumpSequenceId)) { +				_gameSys->setAnimation(0x74, 256, 0); +				_gameSys->insertSequence(0x74, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, scene51_getPosRight(_s51_platypusJumpSequenceId) - 362, 0); +				_s51_platypusSequenceId = 0x74; +			} else { +				_gameSys->setAnimation(0x75, 256, 0); +				_gameSys->insertSequence(0x75, 256, _s51_platypusSequenceId, 256, kSeqSyncWait, 0, scene51_getPosLeft(_s51_platypusJumpSequenceId) - 341, 0); +				_s51_platypusSequenceId = 0x75; +			} +			scene51_waitForAnim(0); +			isIdle = true; +		} + +	} + +	clearKeyStatus1(Common::KEYCODE_ESCAPE); +	clearKeyStatus1(Common::KEYCODE_UP); +	clearKeyStatus1(Common::KEYCODE_SPACE); +	clearKeyStatus1(Common::KEYCODE_RIGHT); +	clearKeyStatus1(Common::KEYCODE_LEFT); + +	_gameSys->setAnimation(0, 0, 0); +	for (int i = 0; i < 6; ++i) +		_gameSys->setAnimation(0, 0, i + 1); + +	showCursor(); + +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene52.cpp b/engines/gnap/scenes/scene52.cpp new file mode 100644 index 0000000000..62cc2f3728 --- /dev/null +++ b/engines/gnap/scenes/scene52.cpp @@ -0,0 +1,907 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +int GnapEngine::scene52_init() { +	scene52_initAnims(); +	return 0x2B; +} + +void GnapEngine::scene52_updateHotspots() { +	_hotspotsCount = 0; +} + +void GnapEngine::scene52_update() { +	 +	for (int rowNum = 0; rowNum < 7; ++rowNum) { +		gameUpdateTick(); +		if (_gameSys->getAnimationStatus(_s52_alienRowAnims[rowNum]) == 2) { +			scene52_updateAlienRow(rowNum); +			rowNum = 0; +		} +	} + +	if (_s52_liveAlienRows == 0 && !_s52_alienSingle) { +		_s52_alienWave = false; +		playSound(48, 0); +		++_s52_alienCounter; +		if (_s52_alienCounter != 3) { +			_timers[0] = 50; +			_timers[2] = 100; +			_s52_alienRowDownCtr = 0; +			_s52_alienSingle = true; +		} +	} + +	if (_s52_alienSingle && !_timers[0]) { +		scene52_initAliens(); +		_s52_alienSingle = false; +		_timers[2] = 5; +		_s52_alienWave = true; +	} + +	if ((_s52_alienRowDownCtr || _s52_liveAlienRows == 0) && !_s52_alienSingle) { +		scene52_moveDownAlienRow(); +		_s52_alienRowDownCtr = 0; +	} + +	if (isKeyStatus1(Common::KEYCODE_UP) || isKeyStatus1(Common::KEYCODE_SPACE)) { +		clearKeyStatus1(Common::KEYCODE_SPACE); +		clearKeyStatus1(Common::KEYCODE_UP); +		if (!_s52_aliensCount) +			scene52_fireShipCannon(_s52_shipPosX); +	} + +	if (_s52_shipCannonFiring) +		scene52_updateShipCannon(); + +	scene52_fireAlienCannon(); +	scene52_updateAlienCannons(); + +	if (_s52_aliensCount == 1) { +		_s52_alienWave = false; +		_timers[3] = 20; +		_timers[2] = 100; +		++_s52_aliensCount; +	} + +	if (_s52_aliensCount && !_timers[3]) { +		scene52_updateAliens(); +		scene52_loseShip(); +		if (_s52_shipsLeft != 0) { +			_timers[3] = 40; +			while (_timers[3]) { +				scene52_updateAlienCannons(); +				if (_s52_shipCannonFiring) +					scene52_updateShipCannon(); +				gameUpdateTick(); +			} +			scene52_initAliens(); +			_s52_shipPosX = (800 - _s52_shipMidX) / 2; +			_gameSys->setAnimation(_s52_nextUfoSequenceId, 256, 7); +			_gameSys->insertSequence(_s52_nextUfoSequenceId, 256, 0, 0, kSeqNone, 0, _s52_shipPosX, _s52_arcadeScreenBottom); +			_s52_ufoSequenceId = _s52_nextUfoSequenceId; +			_timers[2] = 5; +			_s52_alienWave = true; +		} else { +			_sceneDone = true; +		} +	} + +	if (_timers[1] || scene52_getFreeShipCannon() == -1) { +		_s52_nextUfoSequenceId = 34; +		if (_s52_ufoSequenceId != 34) +			_s52_shipFlag = true; +	} else { +		_s52_nextUfoSequenceId = 34; +		if (_s52_ufoSequenceId != 34) +			_s52_shipFlag = true; +	} + +	if (_s52_shipFlag) { +		if (_gameSys->getAnimationStatus(7) == 2) { +			_gameSys->setAnimation(_s52_nextUfoSequenceId, 256, 7); +			_gameSys->insertSequence(_s52_nextUfoSequenceId, 256, _s52_ufoSequenceId, 256, kSeqSyncWait, 0, _s52_shipPosX, _s52_arcadeScreenBottom); +			_s52_ufoSequenceId = _s52_nextUfoSequenceId; +		} +		_s52_shipFlag = false; +	} + +	if (_s52_alienWave && !_timers[0]) { +		scene52_playSound(); +		int v0 = _s52_alienSpeed; +		if (_s52_alienSpeed >= 10) +			v0 = 10; +		int v1 = v0; +		if (v0 < 2) +			v1 = 2; +		_timers[0] = v1; +	} +} + +void GnapEngine::scene52_initShipCannon(int bottomY) { +	_s52_shipCannonFired = 0; +	_s52_shipCannonWidth = MAX(_gameSys->getSpriteWidthById(14), _gameSys->getSpriteWidthById(16)); +	_s52_shipCannonHeight = MAX(_gameSys->getSpriteHeightById(14), _gameSys->getSpriteHeightById(16)); +	_s52_shipCannonTopY = bottomY - _s52_shipCannonHeight; +	_s52_shipCannonFiring = 0; +} + +void GnapEngine::scene52_initAlienCannons() { +	for (int i = 0; i < 3; ++i) { +		_s52_alienCannonIds[i] = 0; +		_s52_alienCannonFired[i] = 0; +	} +	_s52_alienCannonSequenceIds[0] = 30; +	_s52_alienCannonSequenceIds[1] = 31; +	_s52_alienCannonSequenceIds[2] = 32; +} + +void GnapEngine::scene52_fireShipCannon(int posX) { + +	if (_timers[1]) +		return; + +	int cannonNum = scene52_getFreeShipCannon(); +	if (cannonNum != -1) { +		_s52_shipCannonPosX = _s52_shipMidX / 2 + posX - _s52_shipCannonWidth / 2; +		_s52_shipCannonPosY = _s52_shipCannonTopY; +		_gameSys->setAnimation(0x23, cannonNum + 256, cannonNum + 8); +		_gameSys->insertSequence(0x23, cannonNum + 256, 0, 0, kSeqNone, 0, _s52_shipCannonPosX, _s52_shipCannonPosY); +		playSound(0x2D, 0); +		if (scene52_shipCannonHitShield(cannonNum)) { +			_gameSys->setAnimation(0, 0, cannonNum + 8); +			_gameSys->removeSequence(0x23, cannonNum + 256, 1); +		} else { +			_s52_shipCannonFired = 1; +			_s52_shipCannonPosY -= 13; +			_s52_shipCannonFiring = 1; +		} +		_timers[1] = 5; +	} + +} + +void GnapEngine::scene52_fireAlienCannon() { + +	if (_timers[2]) +		return; + +	int cannonNum = scene52_getFreeAlienCannon(); +	if (cannonNum != -1) { +		int alienX1 = _s52_alienLeftX + _s52_alienRowXOfs[0]; +		int alienX2 = _s52_alienLeftX + _s52_alienRowXOfs[0] + 5 * _s52_alienWidth - (_s52_alienWidth / 2 - 15); +		_s52_alienCannonPosX[cannonNum] = getRandom(alienX2 - alienX1) + alienX1; +		_s52_alienCannonPosY[cannonNum] = 104; +		_s52_alienCannonFired[cannonNum] = 1; +		_gameSys->setAnimation(_s52_alienCannonSequenceIds[cannonNum], _s52_alienCannonIds[cannonNum] + 256, cannonNum + 9); +		_gameSys->insertSequence(_s52_alienCannonSequenceIds[cannonNum], _s52_alienCannonIds[cannonNum] + 256, 0, 0, +			kSeqNone, 0, _s52_alienCannonPosX[cannonNum], _s52_alienCannonPosY[cannonNum]); +		_s52_alienCannonPosY[cannonNum] -= 13; +		_timers[2] = 5; +	} + +} + +int GnapEngine::scene52_getFreeShipCannon() { +	if (!_s52_shipCannonFired) +		return 0; +	return -1; +} + +int GnapEngine::scene52_getFreeAlienCannon() { +	for (int i = 0; i < 3; ++i) +		if (!_s52_alienCannonFired[i]) +			return i; +	return -1; +} + +void GnapEngine::scene52_updateShipCannon() { +	if (_s52_shipCannonFired && _gameSys->getAnimationStatus(8) == 2) { +		_s52_shipCannonPosY -= 13; +		if (_s52_shipCannonPosY - 13 >= 135) { +			if (scene52_updateHitAlien()) { +				_gameSys->setAnimation(0, 0, 8); +				_gameSys->removeSequence(35, 256, 1); +				_s52_shipCannonFired = 0; +				scene52_drawScore(_s52_gameScore); +			} else { +				_gameSys->setAnimation(35, 256, 8); +				_gameSys->insertSequence(35, 256, 35, 256, kSeqSyncWait, 0, _s52_shipCannonPosX, _s52_shipCannonPosY); +				_s52_shipCannonPosY -= 13; +			} +		} else { +			_gameSys->setAnimation(0, 0, 8); +			_gameSys->removeSequence(35, 256, 1); +			_s52_shipCannonFired = 0; +		} +	} +} + +void GnapEngine::scene52_updateAlienCannons() { +	for (int i = 0; i < 3; ++i) { +		if (_s52_alienCannonFired[i] && _gameSys->getAnimationStatus(i + 9) == 2) { +			_s52_alienCannonPosY[i] += 13; +			if (_s52_shipCannonHeight + _s52_alienCannonPosY[i] + 13 <= 550) { +				if (scene52_alienCannonHitShip(i)) { +					_gameSys->setAnimation(0, 0, i + 9); +					_s52_alienCannonFired[i] = 0; +					scene52_shipExplode(); +				} else if (scene52_alienCannonHitShield(i)) { +					_s52_alienCannonFired[i] = 0; +				} else { +					_gameSys->insertSequence(_s52_alienCannonSequenceIds[i], 1 - _s52_alienCannonIds[i] + 256, 0, 0, +						kSeqNone, 0, _s52_alienCannonPosX[i], _s52_alienCannonPosY[i]); +					_gameSys->setAnimation(_s52_alienCannonSequenceIds[i], 1 - _s52_alienCannonIds[i] + 256, i + 9); +					_s52_alienCannonIds[i] = 1 - _s52_alienCannonIds[i]; +					_s52_alienCannonPosY[i] += 13; +				} +			} else { +				_gameSys->setAnimation(0, 0, i + 9); +				_s52_alienCannonFired[i] = 0; +			} +		} +	} +} + +void GnapEngine::scene52_initAliens() { +	 +	if (!_s52_aliensInitialized) { +		scene52_initAlienSize(); +		_s52_aliensInitialized = true; +	} + +	_s52_liveAlienRows = 0; +	_s52_alienSpeed = 0; +	_s52_bottomAlienFlag = false; +	_s52_aliensCount = 0; +	_s52_alienSingle = false; +	_s52_alienRowDownCtr = 0; + +	scene52_initShields(); + +	_s52_alienRowKind[0] = -1; +	_s52_alienRowKind[1] = -1; +	_s52_alienRowKind[2] = -1; +	_s52_alienRowKind[3] = -1; +	_s52_alienRowKind[4] = getRandom(2) != 0 ? 24 : 27; +	_s52_alienRowKind[5] = getRandom(2) != 0 ? 25 : 28; +	_s52_alienRowKind[6] = getRandom(2) != 0 ? 26 : 29; + +	for (int i = 0; i < 7; ++i) { +		_s52_alienRowAnims[i] = i; +		_s52_alienRowXOfs[i] = 0; +		scene52_initAlienRowKind(i, _s52_alienRowKind[i]); +		scene52_insertAlienRow(i); +	} + +} + +void GnapEngine::scene52_initAlienRowKind(int rowNum, int alienKind) { +	for (int i = 0; i < 5; ++i) +		_s52_items[rowNum][i] = alienKind; +} + +void GnapEngine::scene52_insertAlienRow(int rowNum) { +	if (_s52_alienRowKind[rowNum] >= 0) { +		scene52_insertAlienRowAliens(rowNum); +		_s52_alienRowIds[rowNum] = 256; +		_gameSys->setAnimation(_s52_alienRowKind[rowNum], _s52_alienRowIds[rowNum], _s52_alienRowAnims[rowNum]); +		++_s52_liveAlienRows; +	} +} + +void GnapEngine::scene52_insertAlienRowAliens(int rowNum) { +	int xOffs = _s52_alienLeftX; +	int yOffs = _s52_alienTopY - 52 * rowNum - _s52_alienHeight + 10; +	for (int i = 0; i < 5; ++i) { +		if (_s52_items[rowNum][i] >= 0) { +			_gameSys->insertSequence(_s52_items[rowNum][i], i + 256, 0, 0, kSeqNone, 0, xOffs, yOffs); +			++_s52_alienSpeed; +		} +		xOffs += _s52_alienWidth; +	} +} + +void GnapEngine::scene52_updateAlienRow(int rowNum) { +	 +	if (_s52_alienRowKind[rowNum] != -1 && !scene52_checkAlienRow(rowNum)) { +		scene52_updateAlienRowXOfs(); +		_s52_alienRowIds[rowNum] = -1; +		int xOffs = _s52_alienLeftX + _s52_alienRowXOfs[rowNum]; +		int yOffs = _s52_alienTopY - 52 * rowNum - _s52_alienHeight + 10; +		for (int i = 0; i < 5; ++i) { +			if (_s52_items[rowNum][i] >= 0) { +				_gameSys->insertSequence(_s52_items[rowNum][i], i + 256, _s52_items[rowNum][i], i + 256, kSeqSyncWait, 0, xOffs, yOffs); +				if (_s52_alienRowIds[rowNum] == -1) +					_s52_alienRowIds[rowNum] = i + 256; +			} else if (_s52_items[rowNum][i] == -2) { +				_gameSys->removeSequence(_s52_alienRowKind[rowNum], i + 256, 1); +				_s52_items[rowNum][i] = -1; +				--_s52_alienSpeed; +			} +			xOffs += _s52_alienWidth; +		} +		if (_s52_alienRowIds[rowNum] == -1) { +			_gameSys->setAnimation(0, 0, _s52_alienRowAnims[rowNum]); +			// MessageBoxA(0, "No live aliens!", "Error 3:", 0x30u); +		} else { +			_gameSys->setAnimation(_s52_alienRowKind[rowNum], _s52_alienRowIds[rowNum], _s52_alienRowAnims[rowNum]); +		} +		if (rowNum == 1) { +			for (int j = 0; j < 3; ++j) { +				if (_s52_shieldSpriteIds[j] != -1) { +					_gameSys->fillSurface(0, _s52_shieldPosX[j], _s52_arcadeScreenBottom - 44, 33, 44, 0, 0, 0); +					_s52_shieldSpriteIds[j] = -1; +				} +			} +		} +		if (rowNum == 0 && _s52_bottomAlienFlag) +			scene52_shipExplode(); +	} +} + +void GnapEngine::scene52_moveDownAlienRow() { + +	int v2[5], v3, v1, v0, v4; +	 +	for (int i = 0; i < 5; ++i) +		v2[i] = _s52_items[0][i]; + +	v3 = _s52_alienRowIds[0]; +	v1 = _s52_alienRowAnims[0]; +	v0 = _s52_alienRowKind[0]; +	v4 = _s52_alienRowXOfs[0]; + +	for (int j = 0; j < 7; ++j) { +		for (int i = 0; i < 5; ++i) +			_s52_items[j][i] = _s52_items[j + 1][i]; +		_s52_alienRowIds[j] = _s52_alienRowIds[j + 1]; +		_s52_alienRowAnims[j] = _s52_alienRowAnims[j + 1]; +		_s52_alienRowKind[j] = _s52_alienRowKind[j + 1]; +		_s52_alienRowXOfs[j] = _s52_alienRowXOfs[j + 1]; +	} + +	for (int i = 0; i < 5; ++i) +		_s52_items[6][i] = v2[i]; + +	_s52_alienRowIds[6] = v3; +	_s52_alienRowAnims[6] = v1; +	_s52_alienRowKind[6] = v0; +	_s52_alienRowXOfs[6] = v4; + +	scene52_updateAlien(6); +	scene52_initAlienRowKind(6, _s52_alienRowKind[6]); +	scene52_insertAlienRow(6); + +	_s52_bottomAlienFlag = _s52_alienRowKind[0] > -1; +} + +int GnapEngine::scene52_updateHitAlien() { +	int result = 0, rowNum, ya; +	 +	int y = _s52_shipCannonTopY - _s52_shipCannonPosY; + +	if (y == 26) { +		rowNum = 1; +		ya = _s52_shipCannonPosY + 26; +	} else { +		if (y % 52) +			return 0; +		rowNum = y / 52 + 1; +		ya = _s52_shipCannonPosY; +	} + +	if (rowNum < 7) { +		int hitAlienNum = scene52_getHitAlienNum(rowNum); +		if (hitAlienNum != -1 && _s52_items[rowNum][hitAlienNum] >= 0) { +			_s52_gameScore = ((_s52_items[rowNum][hitAlienNum] - 24) % 3 + _s52_gameScore + 1) % 1000; +			_s52_items[rowNum][hitAlienNum] = -2; +			playSound(44, 0); +			_gameSys->insertSequence(0x21, 266, 0, 0, +				kSeqNone, 0, _s52_alienLeftX + hitAlienNum * _s52_alienWidth + _s52_alienRowXOfs[rowNum] - 10, ya - _s52_alienHeight); +			result = 1; +		} +	} +	 +	return result; +} + +int GnapEngine::scene52_getHitAlienNum(int rowNum) { +	 +	int result = -1; + +	int v3 = _s52_alienLeftX + _s52_alienRowXOfs[rowNum]; + +	if (_s52_shipCannonPosX >= v3) { +		int v8 = _s52_alienWidth / 2 - 15; +		if (v3 + 5 * _s52_alienWidth - v8 >= _s52_shipCannonPosX) { +			int v4 = v3 + _s52_alienWidth; +			if (_s52_shipCannonPosX >= v4 - v8) { +				int v5 = v4 + _s52_alienWidth; +				if (_s52_shipCannonPosX >= v5 - v8) { +					int v6 = v5 + _s52_alienWidth; +					if (_s52_shipCannonPosX >= v6 - v8) { +						int v7 = v6 + _s52_alienWidth; +						if (_s52_shipCannonPosX >= v7 - v8) { +							if (_s52_shipCannonPosX >= v7 + _s52_alienWidth - v8) +								result = -1; +							else +								result = 4; +						} else { +							result = 3; +						} +					} else { +						result = 2; +					} +				} else { +					result = 1; +				} +			} else { +				result = 0; +			} +		} else { +			result = -1; +		} +	} else { +		result = -1; +	} +	return result; +} + +int GnapEngine::scene52_alienCannonHitShip(int cannonNum) { +	int result = 0; +	 +	if (_s52_aliensCount) { +		result = 0; +	} else { +		int cannonY = _s52_alienCannonPosY[cannonNum] - 13; +		if (_s52_arcadeScreenBottom <= cannonY) { +			if (_s52_shipMidY + _s52_arcadeScreenBottom > cannonY) { +				if (_s52_alienCannonPosX[cannonNum] >= _s52_shipPosX) +					result = _s52_alienCannonPosX[cannonNum] < _s52_shipMidX + _s52_shipPosX; +				else +					result = 0; +			} else { +				result = 0; +			} +		} else { +			result = 0; +		} +	} +	return result; +} + +int GnapEngine::scene52_alienCannonHitShield(int cannonNum) { +	int result = 0; +	 +	int v3 = _s52_alienCannonPosY[cannonNum] + 39; +	if (_s52_arcadeScreenBottom - 44 > v3) +		return 0; + +	if (_s52_arcadeScreenBottom <= v3) +		return 0; + +	if (_s52_alienCannonPosX[cannonNum] < _s52_shieldPosX[0]) +		return 0; + +	if (_s52_alienCannonPosX[cannonNum] > _s52_shieldPosX[2] + 33) +		return 0; + +	int shieldNum = -1; +	if (_s52_alienCannonPosX[cannonNum] < _s52_shieldPosX[0] + 33) +		shieldNum = 0; + +	if (shieldNum < 0 && _s52_alienCannonPosX[cannonNum] < _s52_shieldPosX[1]) +		return 0; + +	if (shieldNum < 0 && _s52_alienCannonPosX[cannonNum] < _s52_shieldPosX[1] + 33) +		shieldNum = 1; + +	if (shieldNum < 0) { +		if (_s52_alienCannonPosX[cannonNum] < _s52_shieldPosX[2]) +			return 0; +		shieldNum = 2; +	} +	 +	if (_s52_shieldSpriteIds[shieldNum] == -1) { +		result = 0; +	} else { +		++_s52_shieldSpriteIds[shieldNum]; +		if (_s52_shieldSpriteIds[shieldNum] <= 21) { +			_gameSys->drawSpriteToBackground(_s52_shieldPosX[shieldNum], _s52_arcadeScreenBottom - 44, _s52_shieldSpriteIds[shieldNum]); +		} else { +			_gameSys->fillSurface(0, _s52_shieldPosX[shieldNum], _s52_arcadeScreenBottom - 44, 33, 44, 0, 0, 0); +			_s52_shieldSpriteIds[shieldNum] = -1; +		} +		_gameSys->setAnimation(0, 0, cannonNum + 9); +		_gameSys->insertSequence(0x21, shieldNum + 257, 0, 0, kSeqNone, 0, _s52_alienCannonPosX[cannonNum] - 18, _s52_arcadeScreenBottom - 44); +		playSound(0x2C, 0); +		result = 1; +	} + +	return result; +} + +int GnapEngine::scene52_shipCannonHitShield(int cannonNum) { +	int result = 0; +	 +	if (_s52_shipCannonPosX < _s52_shieldPosX[0]) +		return 0; + +	if (_s52_shipCannonPosX > _s52_shieldPosX[2] + 33) +		return 0; + +	int shieldNum = -1; +	if (_s52_shipCannonPosX < _s52_shieldPosX[0] + 33) +		shieldNum = 0; + +	if (shieldNum < 0 && _s52_shipCannonPosX < _s52_shieldPosX[1]) +		return 0; + +	if (shieldNum < 0 && _s52_shipCannonPosX < _s52_shieldPosX[1] + 33) +		shieldNum = 1; + +	if (shieldNum < 0) { +		if (_s52_shipCannonPosX < _s52_shieldPosX[2]) +			return 0; +		shieldNum = 2; +	} + +	if (_s52_shieldSpriteIds[shieldNum] == -1) { +		result = 0; +	} else { +		++_s52_shieldSpriteIds[shieldNum]; +		if (_s52_shieldSpriteIds[shieldNum] <= 21) { +			_gameSys->drawSpriteToBackground(_s52_shieldPosX[shieldNum], _s52_arcadeScreenBottom - 44, _s52_shieldSpriteIds[shieldNum]); +		} else { +			_gameSys->fillSurface(0, _s52_shieldPosX[shieldNum], _s52_arcadeScreenBottom - 44, 33, 44, 0, 0, 0); +			_s52_shieldSpriteIds[shieldNum] = -1; +		} +		_gameSys->insertSequence(0x21, shieldNum + 257, 0, 0, kSeqNone, 0, _s52_shipCannonPosX - 18, _s52_arcadeScreenBottom - 44); +		playSound(0x2C, 0); +		result = 1; +	} + +	return result; +} + +int GnapEngine::scene52_shipCannonHitAlien() { +	int result = 0; +	 +	if (_s52_aliensCount) { +		result = 0; +	} else if (scene52_checkAlienRow(0)) { +		result = 0; +	} else { +		int v1 = _s52_alienLeftX + _s52_alienRowXOfs[0]; +		if (_s52_shipMidX + _s52_shipPosX >= _s52_alienLeftX + _s52_alienRowXOfs[0]) { +			int v7 = _s52_alienWidth / 2 - 15; +			if (v1 + 5 * _s52_alienWidth - v7 >= _s52_shipPosX) { +				int v2 = v1 + _s52_alienWidth; +				if (_s52_items[0][0] <= -1 || v2 - v7 <= _s52_shipPosX) { +					int v3 = v2 + _s52_alienWidth; +					if (_s52_items[0][1] <= -1 || v3 - v7 <= _s52_shipPosX) { +						int v4 = v3 + _s52_alienWidth; +						if (_s52_items[0][2] <= -1 || v4 - v7 <= _s52_shipPosX) { +							int v5 = v4 + _s52_alienWidth; +							if (_s52_items[0][3] <= -1 || v5 - v7 <= _s52_shipPosX) { +								int v6 = v5 + _s52_alienWidth; +								result = _s52_items[0][4] > -1 && v6 - v7 > _s52_shipPosX; +							} else { +								result = 1; +							} +						} else { +							result = 1; +						} +					} else { +						result = 1; +					} +				} else { +					result = 1; +				} +			} else { +				result = 0; +			} +		} else { +			result = 0; +		} +	} + +	return result; +} + +void GnapEngine::scene52_shipExplode() { +	if (!_s52_aliensCount) { +		_gameSys->setAnimation(0, 0, 7); +		_gameSys->removeSequence(_s52_ufoSequenceId, 256, 1); +		playSound(44, 0); +		_gameSys->insertSequence(0x21, 266, 0, 0, kSeqNone, 0, _s52_shipPosX, _s52_arcadeScreenBottom); +		_s52_aliensCount = 1; +		playSound(0x31, 0); +	} +} + +int GnapEngine::scene52_checkAlienRow(int rowNum) { + +	int v4 = 0; + +	for (int i = 0; i < 5; ++i) +		if (_s52_items[rowNum][i] >= 0) +			return 0; + +	for (int j = 0; j < 5; ++j) +		if (_s52_items[rowNum][j] == -2) { +			_gameSys->removeSequence(_s52_alienRowKind[rowNum], j + 256, 1); +			_s52_items[rowNum][j] = -1; +			--_s52_alienSpeed; +			v4 = 1; +		} + +	if (v4) { +		_gameSys->setAnimation(0, 0, _s52_alienRowAnims[rowNum]); +		--_s52_liveAlienRows; +	} + +	if (_s52_liveAlienRows < 0) +		_s52_liveAlienRows = 0; + +	return 1; +} + +void GnapEngine::scene52_updateAlienRowXOfs() { +	 +	int amount = 2 * (3 - _s52_liveAlienRows) + 1; + +	if (_s52_alienSpeed == 2) +		amount *= 4; +	else if (_s52_alienSpeed == 1) +		amount *= 10; + +	if (_s52_alienDirection) { +		for (int i = 0; i < 7; ++i) { +			_s52_alienRowXOfs[i] -= amount; +			if (_s52_alienRowXOfs[i] <= -100) { +				_s52_alienRowXOfs[i] = -100; +				_s52_alienDirection = 0; +				++_s52_alienRowDownCtr; +			} +		} +	} else { +		for (int j = 0; j < 7; ++j) { +			_s52_alienRowXOfs[j] += amount; +			if (_s52_alienRowXOfs[j] >= 100) { +				_s52_alienRowXOfs[j] = 100; +				_s52_alienDirection = 1; +				++_s52_alienRowDownCtr; +			} +		} +	} + +} + +void GnapEngine::scene52_initAlienSize() { + +	_s52_alienWidth = _gameSys->getSpriteWidthById(0); +	if (_gameSys->getSpriteWidthById(1) > _s52_alienWidth) +		_s52_alienWidth = _gameSys->getSpriteWidthById(1); +	if (_gameSys->getSpriteWidthById(4) > _s52_alienWidth) +		_s52_alienWidth = _gameSys->getSpriteWidthById(4); +	if (_gameSys->getSpriteWidthById(5) > _s52_alienWidth) +		_s52_alienWidth = _gameSys->getSpriteWidthById(5); +	if (_gameSys->getSpriteWidthById(12) > _s52_alienWidth) +		_s52_alienWidth = _gameSys->getSpriteWidthById(12); +	if (_gameSys->getSpriteWidthById(13) > _s52_alienWidth) +		_s52_alienWidth = _gameSys->getSpriteWidthById(13); + +	_s52_alienHeight = _gameSys->getSpriteHeightById(0); +	if (_gameSys->getSpriteHeightById(1) > _s52_alienHeight) +		_s52_alienHeight = _gameSys->getSpriteHeightById(1); +	if (_gameSys->getSpriteHeightById(4) > _s52_alienHeight) +		_s52_alienHeight = _gameSys->getSpriteHeightById(4); +	if (_gameSys->getSpriteHeightById(5) > _s52_alienHeight) +		_s52_alienHeight = _gameSys->getSpriteHeightById(5); +	if (_gameSys->getSpriteHeightById(12) > _s52_alienHeight) +		_s52_alienHeight = _gameSys->getSpriteHeightById(12); +	if (_gameSys->getSpriteHeightById(13) > _s52_alienHeight) +		_s52_alienHeight = _gameSys->getSpriteHeightById(13); + +	_s52_alienTopY = _s52_shipCannonTopY + 52; +	_s52_alienLeftX = (800 - 5 * _s52_alienWidth) / 2; + +} + +void GnapEngine::scene52_playSound() { +	if (_s52_soundToggle) { +		playSound(0x2F, 0); +		_s52_soundToggle = false; +	} else { +		playSound(0x2E, 0); +		_s52_soundToggle = true; +	} +} + +void GnapEngine::scene52_updateAliens() { +	for (int i = 0; i < 7; ++i) +		scene52_updateAlien(i); +} + +void GnapEngine::scene52_updateAlien(int rowNum) { +	if (_s52_alienRowKind[rowNum] >= 0 && !scene52_checkAlienRow(rowNum)) { +		for (int i = 0; i < 5; ++i) +			if (_s52_items[rowNum][i] >= 0) +				_s52_items[rowNum][i] = -2; +		scene52_checkAlienRow(rowNum); +	} +} + +void GnapEngine::scene52_loseShip() { +	--_s52_shipsLeft; +	if (_s52_shipsLeft == 2) { +		_gameSys->fillSurface(0, 120, 140, _s52_shipMidX, _s52_shipMidY, 0, 0, 0); +	} else if (_s52_shipsLeft == 1) { +		_gameSys->fillSurface(0, 120, 185, _s52_shipMidX, _s52_shipMidY, 0, 0, 0); +	} +} + +void GnapEngine::scene52_initShields() { +	for (int i = 0; i < 3; ++i) { +		_gameSys->drawSpriteToBackground(_s52_shieldPosX[i], _s52_arcadeScreenBottom - 44, 17); +		_s52_shieldSpriteIds[i] = 17; +	} +} + +void GnapEngine::scene52_initAnims() { +	for (int i = 0; i < 7; ++i) +		_gameSys->setAnimation(0, 0, i); +	_gameSys->setAnimation(0, 0, 7); +	for (int j = 0; j < 1; ++j) +		_gameSys->setAnimation(0, 0, j + 8); +	for (int k = 0; k < 3; ++k) +		_gameSys->setAnimation(0, 0, k + 9); +} + +void GnapEngine::scene52_drawScore(int a1) { +	char str[4]; +	sprintf(str, "%03d", a1); +	_gameSys->fillSurface(0, 420, 80, 48, 30, 0, 0, 0); +	_gameSys->drawTextToSurface(0, 420, 80, 255, 255, 255, str); +} + +void GnapEngine::scene52_run() { + +	_timers[1] = 0; +	 +	hideCursor(); + +	// TODO loadFont("maturasc", "Matura MT Script Capitals", 2000); +	// TODO setFontSize(24); + +	_s52_gameScore = 0; +	_gameSys->drawTextToSurface(0, 300, 80, 255, 255, 255, "SCORE"); +	_gameSys->drawTextToSurface(0, 468, 80, 255, 255, 255, "0"); + +	scene52_drawScore(0); + +	_s52_shipMidX = 33; +	_s52_shipMidY = _gameSys->getSpriteHeightById(15); +	_s52_shipPosX = (800 - _s52_shipMidX) / 2; +	_s52_arcadeScreenBottom = 496; +	_s52_arcadeScreenRight = 595 - _s52_shipMidX; +	_s52_arcadeScreenLeft = 210; +	_s52_shipsLeft = 3; +	_s52_alienCounter = 0; + +	_s52_shieldPosX[0] = 247; +	_s52_shieldPosX[1] = 387; +	_s52_shieldPosX[2] = 525; + +	for (int i = 0; i < 3; ++i) +		_s52_shieldSpriteIds[i] = -1; + +	_gameSys->drawSpriteToBackground(120, 140, 0xF); +	_gameSys->drawSpriteToBackground(120, 185, 0xF); + +	scene52_initShipCannon(_s52_arcadeScreenBottom); +	scene52_initAlienCannons(); +	scene52_initAliens(); + +	_s52_nextUfoSequenceId = 0x22; +	_gameSys->setAnimation(0x22, 256, 7); +	_gameSys->insertSequence(_s52_nextUfoSequenceId, 256, 0, 0, kSeqNone, 0, _s52_shipPosX, _s52_arcadeScreenBottom); + +	_s52_ufoSequenceId = _s52_nextUfoSequenceId; + +	clearKeyStatus1(Common::KEYCODE_RIGHT); +	clearKeyStatus1(Common::KEYCODE_LEFT); +	clearKeyStatus1(Common::KEYCODE_SPACE); +	clearKeyStatus1(Common::KEYCODE_UP); +	clearKeyStatus1(Common::KEYCODE_ESCAPE); + +	_timers[2] = 5; +	_s52_shipFlag = false; + +	_timers[0] = 10; +	_s52_alienWave = true; + +	while (!_sceneDone) { + +		gameUpdateTick(); + +		while (isKeyStatus2(Common::KEYCODE_RIGHT)) { +			scene52_update(); +			if (_gameSys->getAnimationStatus(7) == 2) { +				if (_s52_shipPosX < _s52_arcadeScreenRight) { +					_s52_shipPosX += 15; +					if (_s52_shipPosX > _s52_arcadeScreenRight) +						_s52_shipPosX = _s52_arcadeScreenRight; +					_gameSys->setAnimation(_s52_nextUfoSequenceId, 256, 7); +					_gameSys->insertSequence(_s52_nextUfoSequenceId, 256, _s52_ufoSequenceId, 256, kSeqSyncWait, 0, _s52_shipPosX, _s52_arcadeScreenBottom); +					_s52_ufoSequenceId = _s52_nextUfoSequenceId; +					if (_s52_bottomAlienFlag && scene52_shipCannonHitAlien()) +						scene52_shipExplode(); +				} +				break; +			} +		} + +		while (isKeyStatus2(Common::KEYCODE_LEFT)) { +			scene52_update(); +			if (_gameSys->getAnimationStatus(7) == 2) { +				if (_s52_shipPosX > _s52_arcadeScreenLeft) { +					_s52_shipPosX -= 15; +					if (_s52_shipPosX < _s52_arcadeScreenLeft) +						_s52_shipPosX = _s52_arcadeScreenLeft; +					_gameSys->setAnimation(_s52_nextUfoSequenceId, 256, 7); +					_gameSys->insertSequence(_s52_nextUfoSequenceId, 256, _s52_ufoSequenceId, 256, kSeqSyncWait, 0, _s52_shipPosX, _s52_arcadeScreenBottom); +					_s52_ufoSequenceId = _s52_nextUfoSequenceId; +					if (_s52_bottomAlienFlag && scene52_shipCannonHitAlien()) +						scene52_shipExplode(); +				} +				break; +			} +		} +		 +		scene52_update(); +		 +		if (sceneXX_sub_4466B1()) { +			_s52_alienWave = false; +			_gameSys->waitForUpdate(); +			scene52_initAnims(); +			clearKeyStatus1(30); +			_sceneDone = true; +		} + +	} + +	// TODO freeFont(); + +	_gameSys->waitForUpdate(); +	 +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene53.cpp b/engines/gnap/scenes/scene53.cpp new file mode 100644 index 0000000000..20486eb34e --- /dev/null +++ b/engines/gnap/scenes/scene53.cpp @@ -0,0 +1,383 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +int GnapEngine::scene53_init() { +	_gameSys->setAnimation(0, 0, 0); +	_gameSys->setAnimation(0, 0, 1); +	return 0x75; +} + +void GnapEngine::scene53_updateHotspots() { +	setHotspot(0, 0, 0, 0, 0, SF_WALKABLE | SF_TALK_CURSOR | SF_GRAB_CURSOR | SF_LOOK_CURSOR); +	setHotspot(2, 336, 361, 238, 270, SF_GRAB_CURSOR); +	setHotspot(3, 376, 405, 243, 274, SF_GRAB_CURSOR); +	setHotspot(4, 415, 441, 248, 276, SF_GRAB_CURSOR); +	setHotspot(5, 329, 358, 276, 303, SF_GRAB_CURSOR); +	setHotspot(6, 378, 408, 282, 311, SF_GRAB_CURSOR); +	setHotspot(7, 417, 446, 286, 319, SF_GRAB_CURSOR); +	setHotspot(8, 332, 361, 311, 342, SF_GRAB_CURSOR); +	setHotspot(9, 376, 407, 318, 349, SF_GRAB_CURSOR); +	setHotspot(10, 417, 447, 320, 353, SF_GRAB_CURSOR); +	setHotspot(11, 377, 405, 352, 384, SF_GRAB_CURSOR); +	setHotspot(12, 419, 450, 358, 394, SF_GRAB_CURSOR); +	setHotspot(13, 328, 359, 346, 379, SF_GRAB_CURSOR); +	setHotspot(14, 150, 650, 585, 600, SF_EXIT_D_CURSOR); +	setDeviceHotspot(1, -1, -1, -1, -1); +	_hotspotsCount = 15; +} + +int GnapEngine::scene53_pressPhoneNumberButton(int phoneNumber, int buttonNum) { + +	static const int kGnapHandSequenceIds[13] = { +		0x00,  +		0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, +		0x4C, 0x4D, 0x4E, 0x50, 0x51, 0x4F +	}; + +	static const int kPlatypusHandSequenceIds[13] = { +		0x00, +		0x52, 0x53, 0x54, 0x55, 0x56, 0x57, +		0x58, 0x59, 0x5A, 0x5C, 0x5D, 0x5B +	}; + +	if (_s53_isGnapPhoning) { +		_gameSys->setAnimation(kGnapHandSequenceIds[buttonNum], 40, 6); +		_gameSys->insertSequence(kGnapHandSequenceIds[buttonNum], 40, _s53_currHandSequenceId, 40, kSeqSyncWait, 0, 0, 0); +		_s53_currHandSequenceId = kGnapHandSequenceIds[buttonNum]; +	} else { +		_gameSys->setAnimation(kPlatypusHandSequenceIds[buttonNum], 40, 6); +		_gameSys->insertSequence(kPlatypusHandSequenceIds[buttonNum], 40, _s53_currHandSequenceId, 40, kSeqSyncWait, 0, 0, 0); +		_s53_currHandSequenceId = kPlatypusHandSequenceIds[buttonNum]; +	} + +	_gnapActionStatus = 6; +	while (_gameSys->getAnimationStatus(6) != 2) { +		// checkGameAppStatus(); +		updateMouseCursor(); +		gameUpdateTick(); +	} +	_gnapActionStatus = -1; + +	if (buttonNum < 11) +		phoneNumber = buttonNum % 10 + 10 * phoneNumber; + +	return phoneNumber; +} + +int GnapEngine::scene53_getRandomCallIndex() { +	int index, tries = 0; +	if (_s53_callsRndUsed == 0x7FFF) +		_s53_callsRndUsed = 0; +	do { +		index = getRandom(16); +		if (++tries == 300) +			_s53_callsRndUsed = 0; +	} while (_s53_callsRndUsed & (1 << index)); +	_s53_callsRndUsed |= (1 << index); +	return index; +} + +void GnapEngine::scene53_runRandomCall() { + +	static const int kCallSequenceIds[15] = { +		0x60, 0x61, 0x62, 0x63, 0x64, +		0x65, 0x66, 0x67, 0x68, 0x69, +		0x6A, 0x6B, 0x6C, 0x6D, 0x71 +	}; + +	int index; + +	++_s53_callsMadeCtr; + +	if (_s53_callsMadeCtr <= 10) { +		do { +			index = scene53_getRandomCallIndex(); +		} while (!_s53_isGnapPhoning && (index == 0 || index == 3 || index == 4 || index == 11)); +		_gameSys->setAnimation(kCallSequenceIds[index], 1, 6); +		_gameSys->insertSequence(kCallSequenceIds[index], 1, 0, 0, kSeqNone, 16, 0, 0); +	} else { +		_gameSys->setAnimation(0x74, 1, 6); +		_gameSys->insertSequence(0x74, 1, 0, 0, kSeqNone, 16, 0, 0); +		_s53_callsMadeCtr = 0; +	} +	 +	_gnapActionStatus = 1; +	while (_gameSys->getAnimationStatus(6) != 2) { +		updateMouseCursor(); +		// checkGameAppStatus(); +		gameUpdateTick(); +	} +	_gnapActionStatus = -1; + +} + +void GnapEngine::scene53_runChitChatLine() { +	bool flag = false; +	int sequenceId; +	 +	_gameSys->setAnimation(0x6E, 1, 6); +	_gameSys->insertSequence(0x6E, 1, 0, 0, kSeqNone, 16, 0, 0); + +	_gnapActionStatus = 1; +	while (_gameSys->getAnimationStatus(6) != 2) { +		updateMouseCursor(); +		// checkGameAppStatus(); +		gameUpdateTick(); +	} +	_gnapActionStatus = -1; + +	if (isFlag(15)) { +		_gameSys->insertSequence(0x45, 40, _s53_currHandSequenceId, 40, kSeqSyncWait, 0, 0, 0); +		_s53_currHandSequenceId = 0x45; +	} else { +		_gameSys->insertSequence(0x45, 40, _s53_currHandSequenceId, 40, kSeqSyncWait, 0, 0, 0); +		_s53_currHandSequenceId = 0x5E; +	} +	 +	_hotspots[1].flags = SF_DISABLED; +	 +	while (!flag) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 0, -1, -1, -1, -1); +		 +		_sceneClickedHotspot = getClickedHotspotId(); +		 +		updateGrabCursorSprite(0, 0); +		 +		switch (_sceneClickedHotspot) { +		case 2: +			sequenceId = 0x6F; +			flag = 1; +			break; +		case 3: +			sequenceId = 0x70; +			flag = 1; +			break; +		case 4: +			sequenceId = 0x71; +			flag = 1; +			break; +		case 14: +			sequenceId = -1; +			flag = 1; +			_isLeavingScene = true; +			_sceneDone = 1; +			_gnapActionStatus = 0; +			_newSceneNum = 17; +			break; +		case 5: +		case 6: +		case 7: +		case 8: +		case 9: +		case 10: +		case 11: +		case 12: +		case 13: +			scene53_pressPhoneNumberButton(0, _sceneClickedHotspot - 1); +			break; +		} +	 +		if (flag && sequenceId != -1) { +			stopSound(0xA0); +			scene53_pressPhoneNumberButton(0, _sceneClickedHotspot - 1); +			_gnapActionStatus = 1; +			_gameSys->setAnimation(sequenceId, 1, 6); +			_gameSys->insertSequence(sequenceId, 1, 0, 0, kSeqNone, 16, 0, 0); +			_gnapActionStatus = 1; +			while (_gameSys->getAnimationStatus(6) != 2) { +				updateMouseCursor(); +				// checkGameAppStatus(); +				gameUpdateTick(); +			} +			_gnapActionStatus = -1; +			_gameSys->setAnimation(0x72, 1, 6); +			_gameSys->insertSequence(0x72, 1, 0, 0, kSeqNone, 16, 0, 0); +			_gnapActionStatus = 1; +			while (_gameSys->getAnimationStatus(6) != 2) { +				updateMouseCursor(); +				// checkGameAppStatus(); +				gameUpdateTick(); +			} +			_gnapActionStatus = -1; +		} +	 +	} +	 +	scene53_updateHotspots(); +	 +	_gnapActionStatus = 1; +	 +	if (isFlag(15)) { +		_gameSys->setAnimation(0x73, 40, 6); +		_gameSys->insertSequence(0x73, 40, _s53_currHandSequenceId, 40, kSeqSyncWait, 0, 0, 0); +		while (_gameSys->getAnimationStatus(6) != 2) { +			updateMouseCursor(); +			// checkGameAppStatus(); +			gameUpdateTick(); +		} +		_s53_currHandSequenceId = 0x73; +		_gnapActionStatus = -1; +	} + +} + +void GnapEngine::scene53_run() { +	int phoneNumber = 0; +	int phoneNumberLen = 0; +	 +	queueInsertDeviceIcon(); +	 +	if (isFlag(15)) { +		_s53_currHandSequenceId = 0x45; +		_s53_isGnapPhoning = true; +	} else { +		_s53_currHandSequenceId = 0x5E; +		_s53_isGnapPhoning = false; +	} +	 +	_gameSys->insertSequence(_s53_currHandSequenceId, 40, 0, 0, kSeqNone, 0, 0, 0); +	 +	endSceneInit(); +	 +	setVerbCursor(GRAB_CURSOR); +	 +	playSound(0xA0, 1); +	 +	while (!_sceneDone) { +	 +		updateMouseCursor(); +		updateCursorByHotspot(); +	 +		testWalk(0, 0, -1, -1, -1, -1); +	 +		_sceneClickedHotspot = getClickedHotspotId(); +		updateGrabCursorSprite(0, 0); +	 +		switch (_sceneClickedHotspot) { +		case 1: +			if (_gnapActionStatus < 0) { +				runMenu(); +				scene53_updateHotspots(); +			} +			break; +		case 2: +		case 3: +		case 4: +		case 5: +		case 6: +		case 7: +		case 8: +		case 9: +		case 10: +		case 11: +			stopSound(0xA0); +			++phoneNumberLen; +			phoneNumber = scene53_pressPhoneNumberButton(phoneNumber, _sceneClickedHotspot - 1); +			debug("phoneNumber: %d", phoneNumber); +			if (phoneNumberLen == 7) { +				_gnapActionStatus = 1; +				if (isFlag(15)) { +					_gameSys->setAnimation(0x73, 40, 6); +					_gameSys->insertSequence(0x73, 40, _s53_currHandSequenceId, 40, kSeqSyncWait, 0, 0, 0); +					while (_gameSys->getAnimationStatus(6) != 2) { +						updateMouseCursor(); +						// checkGameAppStatus(); +						gameUpdateTick(); +					} +					_s53_currHandSequenceId = 0x73; +					_gnapActionStatus = -1; +				} +				if (phoneNumber == 7284141) { +					scene53_runChitChatLine(); +					phoneNumber = 0; +					phoneNumberLen = 0; +					_sceneDone = 1; +					_newSceneNum = 17; +				} else if (phoneNumber != 5556789 || isFlag(20)) {				 +					scene53_runRandomCall(); +					phoneNumber = 0; +					phoneNumberLen = 0; +					_sceneDone = 1; +					_newSceneNum = 17; +				} else { +					phoneNumber = 0; +					phoneNumberLen = 0; +					_sceneDone = 1; +					_newSceneNum = 17; +					if (_s53_isGnapPhoning) +						setFlag(25); +					else +						setFlag(26); +				} +			} +			break; +		case 12: +		case 13: +			scene53_pressPhoneNumberButton(0, _sceneClickedHotspot - 1); +			break; +		case 14: +			if (_gnapActionStatus < 0) { +				_gnapActionStatus = 1; +				if (isFlag(15)) { +					_gameSys->setAnimation(0x73, 40, 6); +					_gameSys->insertSequence(0x73, 40, _s53_currHandSequenceId, 40, kSeqSyncWait, 0, 0, 0); +					while (_gameSys->getAnimationStatus(6) != 2) { +						updateMouseCursor(); +						// checkGameAppStatus(); +						gameUpdateTick(); +					} +					_s53_currHandSequenceId = 0x73; +					_gnapActionStatus = -1; +				} +				_isLeavingScene = true; +				_sceneDone = 1; +				_gnapActionStatus = 0; +				_newSceneNum = 17; +			} +			break; +		} +	 +		checkGameKeys(); +	 +		if (isKeyStatus1(8)) { +			clearKeyStatus1(8); +			runMenu(); +			scene53_updateHotspots(); +		} +		 +		gameUpdateTick(); +	 +	} +	 +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scene54.cpp b/engines/gnap/scenes/scene54.cpp new file mode 100644 index 0000000000..76bc66b9f3 --- /dev/null +++ b/engines/gnap/scenes/scene54.cpp @@ -0,0 +1,127 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +void GnapEngine::scene54_initCutscene1() { +	_s99_dword_47F370[0] = 0x1BE; +	_s99_dword_47F370[1] = 0x1BF; +	_s99_dword_47F370[2] = 0x1BA; +	_s99_dword_47F370[3] = 0x1BB; +	_s99_dword_47F370[4] = 0x1BD; +	_s99_dword_47F370[5] = 0x1BC; +	_s99_dword_47F2F0[0] = 0x3C; +	_s99_dword_47F2F0[1] = 0x43; +	_s99_dword_47F2F0[2] = 0x44; +	if (isFlag(20)) +		_s99_dword_47F2F0[3] = 0x47; +	else +		_s99_dword_47F2F0[3] = 0x46; +	_s99_dword_47F2F0[4] = 0x45; +	_s99_dword_47F330[0] = 1; +	_s99_dword_47F330[1] = 1; +	_s99_dword_47F330[2] = 1; +	_s99_dword_47F330[3] = 2; +	_s99_dword_47F330[4] = 1; +	_s99_canSkip[0] = 0; +	_s99_canSkip[1] = 0; +	_s99_canSkip[2] = 0; +	_s99_canSkip[3] = 0; +	_s99_canSkip[4] = 0; +	_s99_itemsCount = 5; +} + +void GnapEngine::scene54_initCutscene2() { +	_s99_dword_47F370[0] = 0x1C9; +	_s99_dword_47F370[1] = 0x1C7; +	_s99_dword_47F370[2] = 0x1CC; +	_s99_dword_47F370[3] = 0x1C8; +	_s99_dword_47F370[4] = 0x1CB; +	_s99_dword_47F370[5] = 0x1C0; +	_s99_dword_47F370[6] = 0x1CA; +	_s99_dword_47F370[7] = 0x1CE; +	_s99_dword_47F370[8] = 0x1CD; +	_s99_dword_47F370[9] = 0x1C1; +	_s99_dword_47F370[10] = 0x1C2; +	_s99_dword_47F370[11] = 0x1C3; +	_s99_dword_47F370[12] = 0x1C4; +	_s99_dword_47F370[13] = 0x1C6; +	_s99_dword_47F370[14] = 0x1C5; +	_s99_dword_47F370[15] = 0x1D0; +	_s99_dword_47F370[16] = 0x1D0; +	_s99_dword_47F370[17] = 0x1D0; +	_s99_dword_47F2F0[0] = 0xD5; +	_s99_dword_47F2F0[1] = 0x14C; +	_s99_dword_47F2F0[2] = 0xD5; +	_s99_dword_47F2F0[3] = 0xBF; +	_s99_dword_47F2F0[4] = 0xD6; +	_s99_dword_47F2F0[5] = 0x154; +	_s99_dword_47F2F0[6] = 0x155; +	_s99_dword_47F2F0[7] = 0xB9; +	_s99_dword_47F2F0[8] = 0xBA; +	_s99_dword_47F2F0[9] = 0x17B; +	_s99_dword_47F2F0[10] = 0x17A; +	_s99_dword_47F2F0[11] = 0x17C; +	_s99_dword_47F2F0[12] = 0x17A; +	_s99_dword_47F2F0[13] = 0x1B7; +	_s99_dword_47F2F0[14] = 0x1B8; +	_s99_dword_47F2F0[15] = 0x1B9; +	_s99_dword_47F330[0] = 2; +	_s99_dword_47F330[1] = 1; +	_s99_dword_47F330[2] = 2; +	_s99_dword_47F330[3] = 1; +	_s99_dword_47F330[4] = 1; +	_s99_dword_47F330[5] = 1; +	_s99_dword_47F330[6] = 1; +	_s99_dword_47F330[7] = 1; +	_s99_dword_47F330[8] = 1; +	_s99_dword_47F330[9] = 1; +	_s99_dword_47F330[10] = 1; +	_s99_dword_47F330[11] = 1; +	_s99_dword_47F330[12] = 1; +	_s99_dword_47F330[13] = 1; +	_s99_dword_47F330[14] = 1; +	_s99_dword_47F330[15] = 1; +	_s99_canSkip[0] = 0; +	_s99_canSkip[1] = 0; +	_s99_canSkip[2] = 0; +	_s99_canSkip[3] = 0; +	_s99_canSkip[4] = 0; +	_s99_canSkip[5] = 0; +	_s99_canSkip[6] = 0; +	_s99_canSkip[7] = 0; +	_s99_canSkip[8] = 0; +	_s99_canSkip[9] = 0; +	_s99_canSkip[10] = 0; +	_s99_canSkip[11] = 0; +	_s99_canSkip[12] = 0; +	_s99_canSkip[13] = 1; +	_s99_canSkip[14] = 1; +	_s99_canSkip[15] = 0; +	_s99_itemsCount = 16; +} + +} // End of namespace Gnap diff --git a/engines/gnap/scenes/scenecore.cpp b/engines/gnap/scenes/scenecore.cpp new file mode 100644 index 0000000000..2736addb31 --- /dev/null +++ b/engines/gnap/scenes/scenecore.cpp @@ -0,0 +1,658 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +int GnapEngine::initSceneLogic() { + +	int backgroundId = -1; + +	switch (_currentSceneNum) { +#if 0 // TODO			 +	case 0: +		backgroundId = scene00_init(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		break; +#endif			 +	case 1: +		backgroundId = scene01_init(); +		scene01_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 2: +		backgroundId = scene02_init(); +		scene02_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 3: +		backgroundId = scene03_init(); +		scene03_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 4: +		backgroundId = scene04_init(); +		scene04_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 5: +		backgroundId = scene05_init(); +		scene05_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 6: +		backgroundId = scene06_init(); +		scene06_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 7: +		backgroundId = scene07_init(); +		scene07_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 8: +		backgroundId = scene08_init(); +		scene08_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 9: +		backgroundId = scene09_init(); +		scene09_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 10: +		backgroundId = scene10_init(); +		scene10_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 11: +		backgroundId = scene11_init(); +		scene11_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 12: +		backgroundId = scene12_init(); +		scene12_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 13: +		backgroundId = scene13_init(); +		scene13_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 14: +		backgroundId = scene14_init(); +		scene14_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		break; +	case 15: +		backgroundId = scene15_init(); +		scene15_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		break; +	case 16: +	case 47: +	case 48: +	case 54: +		backgroundId = cutscene_init(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		break; +	case 17: +		backgroundId = scene17_init(); +		scene17_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 18: +		backgroundId = scene18_init(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		scene18_updateHotspots(); +		break; +	case 19: +		backgroundId = scene19_init(); +		scene19_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 20: +		backgroundId = scene20_init(); +		scene20_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 21: +		backgroundId = scene21_init(); +		scene21_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 22: +		backgroundId = scene22_init(); +		scene22_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 23: +		backgroundId = scene23_init(); +		scene23_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 24: +		backgroundId = scene24_init(); +		scene24_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 136, 11, 10); +		break; +	case 25: +		backgroundId = scene25_init(); +		scene25_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 26: +		backgroundId = scene26_init(); +		scene26_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 27: +		backgroundId = scene27_init(); +		scene27_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 28: +		backgroundId = scene28_init(); +		scene28_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 29: +		backgroundId = scene29_init(); +		scene29_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 30: +		backgroundId = scene30_init(); +		scene30_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 31: +		backgroundId = scene31_init(); +		scene31_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 32: +		backgroundId = scene32_init(); +		scene32_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 33: +		backgroundId = scene33_init(); +		scene33_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 34: +		backgroundId = scene03_init(); +		scene03_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 35: +		backgroundId = scene05_init(); +		scene05_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 36: +		backgroundId = scene06_init(); +		scene06_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 37: +		backgroundId = scene04_init(); +		scene04_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 38: +		backgroundId = scene38_init(); +		scene38_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 39: +		backgroundId = scene39_init(); +		scene39_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 40: +		backgroundId = scene40_init(); +		scene40_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 41: +		backgroundId = scene41_init(); +		scene41_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 42: +		backgroundId = scene42_init(); +		scene42_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 43: +		backgroundId = scene43_init(); +		scene43_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 44: +		backgroundId = scene44_init(); +		scene44_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 45: +		backgroundId = scene45_init(); +		scene45_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 46: +		backgroundId = scene46_init(); +		scene46_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 49: +		backgroundId = scene49_init(); +		scene49_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 50: +		backgroundId = scene50_init(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 51: +		backgroundId = scene51_init(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 52: +		backgroundId = scene52_init(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	case 53: +		backgroundId = scene53_init(); +		scene53_updateHotspots(); +		_gameSys->setScaleValues(0, 500, 1, 1000); +		initSceneGrid(21, 146, 11, 10); +		break; +	} + +	return backgroundId; +} + +void GnapEngine::runSceneLogic() { +	switch (_currentSceneNum) { +	case 0: +#if 0 // TODO				 +		scene00_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 8; +		break; +#endif +	case 1: +		scene01_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 4; +		break; +	case 2: +		scene02_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 4; +		break; +	case 3: +		scene03_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 4; +		break; +	case 4: +		scene04_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 4; +		break; +	case 5: +		scene05_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 4; +		break; +	case 6: +		scene06_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 4; +		break; +	case 7: +		scene07_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 8; +		break; +	case 8: +		scene08_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 9; +		break; +	case 9: +		scene09_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 10; +		break; +	case 10: +		scene10_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 11; +		break; +	case 11: +		scene11_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 12; +		break; +	case 12: +		scene12_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 11; +		break; +	case 13: +		scene13_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 11; +		break; +	case 14: +		scene14_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 13; +		break; +	case 15: +		scene15_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 12; +		break; +	case 16: +		scene16_initCutscene(); +		_newSceneNum = 17; +		_newCursorValue = 3; +		cutscene_run(); +		break; +	case 17: +		scene17_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 20; +		break; +	case 18: +		scene18_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 20; +		break; +	case 19: +		scene19_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 19; +		break; +	case 20: +		scene20_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 22; +		break; +	case 21: +		scene21_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 20; +		break; +	case 22: +		scene22_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 20; +		break; +	case 23: +		scene23_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 20; +		break; +	case 24: +		scene24_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 20; +		break; +	case 25: +		scene25_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 20; +		break; +	case 26: +		scene26_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 20; +		break; +	case 27: +		scene27_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 20; +		break; +	case 28: +		scene28_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 20; +		break; +	case 29: +		scene29_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 20; +		break; +	case 30: +		scene30_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 20; +		break; +	case 31: +		scene31_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 20; +		break; +	case 32: +		scene32_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 37; +		break; +	case 33: +		scene33_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 37; +		break; +	case 34: +		scene03_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 37; +		break; +	case 35: +		scene05_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 37; +		break; +	case 36: +		scene06_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 37; +		break; +	case 37: +		scene04_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 37; +		break; +	case 38: +		scene38_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 37; +		break; +	case 39: +		scene39_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 37; +		break; +	case 40: +		scene40_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 37; +		break; +	case 41: +		scene41_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 37; +		break; +	case 42: +		scene42_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 37; +		break; +	case 43: +		scene43_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 37; +		break; +	case 44: +		scene44_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 37; +		break; +	case 45: +		scene45_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 37; +		break; +	case 46: +		scene46_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 37; +		break; +	case 47: +		if (_prevSceneNum == 49) { +			scene47_initCutscene1(); +			_newSceneNum = 7; +			_newCursorValue = 2; +		} else if (_prevSceneNum == 13) { +			scene47_initCutscene2(); +			_newSceneNum = 11; +		} else if (!isFlag(10) && _prevSceneNum == 2) {//CHECKME +			if (isFlag(25)) { +				scene47_initCutscene3(); +				_newSceneNum = 2; +			} else { +				scene47_initCutscene4(); +				_newSceneNum = 49; +			} +		} else if (_prevSceneNum == 21) { +			scene47_initCutscene5(); +			_newSceneNum = 21; +			setFlag(3); +			setFlag(5); +		} else if (_prevSceneNum == 30) { +			scene47_initCutscene6(); +			_newSceneNum = 26; +		} else if (isFlag(10) && _cursorValue == 1) { +			scene47_initCutscene7(); +			_newSceneNum = 4; +		} +		cutscene_run(); +		break; +	case 48: +		scene48_initCutscene(); +		_newSceneNum = 33; +		_newCursorValue = 4; +		cutscene_run(); +		break; +	case 49: +		scene49_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 47; +		break; +	case 50: +		scene50_run(); +		_newSceneNum = _prevSceneNum; +		break; +	case 51: +		scene51_run(); +		break; +	case 52: +		scene52_run(); +		_newSceneNum = _prevSceneNum; +		break; +	case 53: +		scene53_run(); +		if (_newSceneNum == 55) +			_newSceneNum = 53; +		break; +	case 54: +		if (_prevSceneNum == 45) { +			scene54_initCutscene1(); +			_newSceneNum = 43; +			cutscene_run(); +		} else { +			scene54_initCutscene2(); +			cutscene_run(); +			_gameDone = true; +		} +		break; +	} +} + +} // End of namespace Gnap diff --git a/engines/gnap/sound.cpp b/engines/gnap/sound.cpp new file mode 100644 index 0000000000..9471d12a67 --- /dev/null +++ b/engines/gnap/sound.cpp @@ -0,0 +1,91 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/sound.h" +#include "audio/audiostream.h" +#include "audio/decoders/wave.h" + +namespace Gnap { + +SoundMan::SoundMan(GnapEngine *vm) +	: _vm(vm) { +} + +SoundMan::~SoundMan() { +} + +void SoundMan::playSound(int resourceId, bool looping) { +	SoundItem soundItem; +	soundItem.resourceId = resourceId; +	 +	SoundResource *soundResource = _vm->_soundCache->get(resourceId); +	Common::MemoryReadStream *stream = new Common::MemoryReadStream(soundResource->_data, soundResource->_size, DisposeAfterUse::NO); +	Audio::AudioStream *audioStream = Audio::makeLoopingAudioStream(Audio::makeWAVStream(stream, DisposeAfterUse::YES), looping ? 0 : 1); + +	_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &soundItem.handle, audioStream); +	 +	_items.push_back(soundItem); +	 +} + +void SoundMan::stopSound(int resourceId) { +	const int index = find(resourceId); +	if (index >= 0) { +		_vm->_soundCache->release(_items[index].resourceId); +		_vm->_mixer->stopHandle(_items[index].handle); +		_items.remove_at(index); +	} +} + +void SoundMan::setSoundVolume(int resourceId, int volume) { +	// TODO +} + +bool SoundMan::isSoundPlaying(int resourceId) { +	const int index = find(resourceId); +	return index >= 0 && _vm->_mixer->isSoundHandleActive(_items[index].handle); +} + +void SoundMan::stopAll() { +	for (int index = 0; index < (int)_items.size(); ++index) { +		_vm->_soundCache->release(_items[index].resourceId); +		_vm->_mixer->stopHandle(_items[index].handle); +	} +} + +void SoundMan::update() { +	for (int index = 0; index < (int)_items.size(); ++index) +		if (!_vm->_mixer->isSoundHandleActive(_items[index].handle)) { +			_vm->_soundCache->release(_items[index].resourceId); +			_items.remove_at(index); +			--index; +		} +} + +int SoundMan::find(int resourceId) { +	for (int index = 0; index < (int)_items.size(); ++index) +		if (_items[index].resourceId == resourceId) +			return index; +	return -1; +} + +} // End of namespace Gnap diff --git a/engines/gnap/sound.h b/engines/gnap/sound.h new file mode 100644 index 0000000000..ec5888ed1b --- /dev/null +++ b/engines/gnap/sound.h @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef GNAP_SOUND_H +#define GNAP_SOUND_H + +#include "gnap/gnap.h" +#include "gnap/resource.h" +#include "audio/mixer.h" +#include "common/array.h" + +namespace Gnap { + +struct SoundItem { +	int resourceId; +	Audio::SoundHandle handle; +}; + +class SoundMan { +public: +	SoundMan(GnapEngine *vm); +	~SoundMan(); +	void playSound(int resourceId, bool looping); +	void stopSound(int resourceId); +	void setSoundVolume(int resourceId, int volume); +	bool isSoundPlaying(int resourceId); +	void stopAll(); +	void update(); +protected: +	GnapEngine *_vm; +	Common::Array<SoundItem> _items; +	int find(int resourceId); +}; + +} // End of namespace Gnap + +#endif // GNAP_SOUND_H  | 
