From d0225f753274d9a04045a14dfe9a1b1b8aeae371 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 23 Dec 2014 15:49:35 +1100 Subject: XEEN: Initial commit --- engines/xeen/configure.engine | 3 + engines/xeen/debugger.cpp | 56 +++++++++++ engines/xeen/debugger.h | 44 +++++++++ engines/xeen/detection.cpp | 183 +++++++++++++++++++++++++++++++++++ engines/xeen/detection_tables.h | 48 +++++++++ engines/xeen/module.mk | 13 +++ engines/xeen/xeen.cpp | 209 ++++++++++++++++++++++++++++++++++++++++ engines/xeen/xeen.h | 153 +++++++++++++++++++++++++++++ 8 files changed, 709 insertions(+) create mode 100644 engines/xeen/configure.engine create mode 100644 engines/xeen/debugger.cpp create mode 100644 engines/xeen/debugger.h create mode 100644 engines/xeen/detection.cpp create mode 100644 engines/xeen/detection_tables.h create mode 100644 engines/xeen/module.mk create mode 100644 engines/xeen/xeen.cpp create mode 100644 engines/xeen/xeen.h (limited to 'engines/xeen') diff --git a/engines/xeen/configure.engine b/engines/xeen/configure.engine new file mode 100644 index 0000000000..489254f269 --- /dev/null +++ b/engines/xeen/configure.engine @@ -0,0 +1,3 @@ +# This file is included from the main "configure" script +# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] +add_engine xeen "World of Xeen" no diff --git a/engines/xeen/debugger.cpp b/engines/xeen/debugger.cpp new file mode 100644 index 0000000000..0642498749 --- /dev/null +++ b/engines/xeen/debugger.cpp @@ -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. + * + */ + +#include "common/file.h" +#include "xeen/xeen.h" +#include "xeen/debugger.h" + +namespace Xeen { + +static int strToInt(const char *s) { + if (!*s) + // No string at all + return 0; + else if (toupper(s[strlen(s) - 1]) != 'H') + // Standard decimal string + return atoi(s); + + // Hexadecimal string + uint tmp = 0; + int read = sscanf(s, "%xh", &tmp); + if (read < 1) + error("strToInt failed on string \"%s\"", s); + return (int)tmp; +} + +/*------------------------------------------------------------------------*/ + +Debugger::Debugger(XeenEngine *vm) : GUI::Debugger(), _vm(vm) { + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("scene", WRAP_METHOD(Debugger, Cmd_LoadScene)); +} + +bool Debugger::Cmd_LoadScene(int argc, const char **argv) { + return true; +} + +} // End of namespace Access diff --git a/engines/xeen/debugger.h b/engines/xeen/debugger.h new file mode 100644 index 0000000000..6a1ec12e80 --- /dev/null +++ b/engines/xeen/debugger.h @@ -0,0 +1,44 @@ +/* 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 XEEN_DEBUGGER_H +#define XEEN_DEBUGGER_H + +#include "common/scummsys.h" +#include "gui/debugger.h" + +namespace Xeen { + +class XeenEngine; + +class Debugger : public GUI::Debugger { +protected: + XeenEngine *_vm; + + bool Cmd_LoadScene(int argc, const char **argv); +public: + Debugger(XeenEngine *vm); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DEBUGGER_H */ diff --git a/engines/xeen/detection.cpp b/engines/xeen/detection.cpp new file mode 100644 index 0000000000..2b30478808 --- /dev/null +++ b/engines/xeen/detection.cpp @@ -0,0 +1,183 @@ +/* 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 "xeen/xeen.h" + +#include "base/plugins.h" +#include "common/savefile.h" +#include "engines/advancedDetector.h" +#include "common/system.h" + +#define MAX_SAVES 99 + +namespace Xeen { + +struct XeenGameDescription { + ADGameDescription desc; + + int gameID; + uint32 features; +}; + +uint32 XeenEngine::getGameID() const { + return _gameDescription->gameID; +} + +uint32 XeenEngine::getGameFeatures() const { + return _gameDescription->features; +} + +uint32 XeenEngine::getFeatures() const { + return _gameDescription->desc.flags; +} + +Common::Language XeenEngine::getLanguage() const { + return _gameDescription->desc.language; +} + +Common::Platform XeenEngine::getPlatform() const { + return _gameDescription->desc.platform; +} + +} // End of namespace Xeen + +static const PlainGameDescriptor XeenGames[] = { + { "xeen", "Xeen" }, + { "worldofxeen", "World of Xeen" }, + {0, 0} +}; + +#include "xeen/detection_tables.h" + +class XeenMetaEngine : public AdvancedMetaEngine { +public: + XeenMetaEngine() : AdvancedMetaEngine(Xeen::gameDescriptions, sizeof(Xeen::XeenGameDescription), XeenGames) { + _maxScanDepth = 3; + } + + virtual const char *getName() const { + return "Xeen Engine"; + } + + virtual const char *getOriginalCopyright() const { + return "Xeen Engine (c) ???"; + } + + virtual bool hasFeature(MetaEngineFeature f) const; + virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; + virtual SaveStateList listSaves(const char *target) const; + virtual int getMaximumSaveSlot() const; + virtual void removeSaveState(const char *target, int slot) const; + SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; +}; + +bool XeenMetaEngine::hasFeature(MetaEngineFeature f) const { + return + (f == kSupportsListSaves) || + (f == kSupportsLoadingDuringStartup) || + (f == kSupportsDeleteSave) || + (f == kSavesSupportMetaInfo) || + (f == kSavesSupportThumbnail); +} + +bool Xeen::XeenEngine::hasFeature(EngineFeature f) const { + return + (f == kSupportsRTL) || + (f == kSupportsLoadingDuringRuntime) || + (f == kSupportsSavingDuringRuntime); +} + +bool XeenMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { + const Xeen::XeenGameDescription *gd = (const Xeen::XeenGameDescription *)desc; + *engine = new Xeen::XeenEngine(syst, gd); + return gd != 0; +} + +SaveStateList XeenMetaEngine::listSaves(const char *target) const { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::StringArray filenames; + Common::String saveDesc; + Common::String pattern = Common::String::format("%s.0??", target); + Xeen::XeenSavegameHeader header; + + filenames = saveFileMan->listSavefiles(pattern); + sort(filenames.begin(), filenames.end()); // Sort to get the files in numerical order + + SaveStateList saveList; + for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + const char *ext = strrchr(file->c_str(), '.'); + int slot = ext ? atoi(ext + 1) : -1; + + if (slot >= 0 && slot < MAX_SAVES) { + Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file); + + if (in) { + Xeen::XeenEngine::readSavegameHeader(in, header); + saveList.push_back(SaveStateDescriptor(slot, header._saveName)); + + header._thumbnail->free(); + delete header._thumbnail; + delete in; + } + } + } + + return saveList; +} + +int XeenMetaEngine::getMaximumSaveSlot() const { + return MAX_SAVES; +} + +void XeenMetaEngine::removeSaveState(const char *target, int slot) const { + Common::String filename = Common::String::format("%s.%03d", target, slot); + g_system->getSavefileManager()->removeSavefile(filename); +} + +SaveStateDescriptor XeenMetaEngine::querySaveMetaInfos(const char *target, int slot) const { + Common::String filename = Common::String::format("%s.%03d", target, slot); + Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename); + + if (f) { + Xeen::XeenSavegameHeader header; + Xeen::XeenEngine::readSavegameHeader(f, header); + delete f; + + // Create the return descriptor + SaveStateDescriptor desc(slot, header._saveName); + desc.setThumbnail(header._thumbnail); + desc.setSaveDate(header._year, header._month, header._day); + desc.setSaveTime(header._hour, header._minute); + desc.setPlayTime(header._totalFrames * GAME_FRAME_TIME); + + return desc; + } + + return SaveStateDescriptor(); +} + + +#if PLUGIN_ENABLED_DYNAMIC(XEEN) + REGISTER_PLUGIN_DYNAMIC(XEEN, PLUGIN_TYPE_ENGINE, XeenMetaEngine); +#else + REGISTER_PLUGIN_STATIC(XEEN, PLUGIN_TYPE_ENGINE, XeenMetaEngine); +#endif diff --git a/engines/xeen/detection_tables.h b/engines/xeen/detection_tables.h new file mode 100644 index 0000000000..e106abf8cd --- /dev/null +++ b/engines/xeen/detection_tables.h @@ -0,0 +1,48 @@ +/* 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. + * + */ + +namespace Xeen { + +static const XeenGameDescription gameDescriptions[] = { + { + // World of Xeen + { + "worldofxeen", + nullptr, + { + { "xeen.cc", 0, "0cffbab533d9afe140e69ec93096f43e", 13435646 }, + { "dark.cc", 0, "df194483ecea6abc0511637d712ced7c", 11217676 }, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + GType_World, + 0 + }, + + { AD_TABLE_END_MARKER, 0, 0 } +}; + +} // End of namespace Xeen diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk new file mode 100644 index 0000000000..a33b26a988 --- /dev/null +++ b/engines/xeen/module.mk @@ -0,0 +1,13 @@ +MODULE := engines/xeen + +MODULE_OBJS := \ + detection.o \ + xeen.o + +# This module can be built as a plugin +ifeq ($(ENABLE_XEEN), DYNAMIC_PLUGIN) +PLUGIN := 1 +endif + +# Include common rules +include $(srcdir)/rules.mk diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp new file mode 100644 index 0000000000..3fe75e10a0 --- /dev/null +++ b/engines/xeen/xeen.cpp @@ -0,0 +1,209 @@ +/* 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/scummsys.h" +#include "common/config-manager.h" +#include "common/debug-channels.h" +#include "common/events.h" +#include "engines/util.h" +#include "graphics/scaler.h" +#include "graphics/thumbnail.h" +#include "xeen/xeen.h" + +namespace Xeen { + +XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) + : _gameDescription(gameDesc), Engine(syst), _randomSource("Xeen") { + _debugger = nullptr; +} + +XeenEngine::~XeenEngine() { + delete _debugger; +} + +void XeenEngine::initialize() { + // Set up debug channels + DebugMan.addDebugChannel(kDebugPath, "Path", "Pathfinding debug level"); + DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts"); + DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics handling"); + DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling"); + + // Create sub-objects of the engine + _debugger = new Debugger(this); + + // Set graphics mode + initGraphics(320, 200, false); + + // If requested, load a savegame instead of showing the intro + if (ConfMan.hasKey("save_slot")) { + int saveSlot = ConfMan.getInt("save_slot"); + if (saveSlot >= 0 && saveSlot <= 999) + _loadSaveSlot = saveSlot; + } +} + +Common::Error XeenEngine::run() { + initialize(); + + playGame(); + + return Common::kNoError; +} + +int XeenEngine::getRandomNumber(int maxNumber) { + return _randomSource.getRandomNumber(maxNumber); +} + +Common::Error XeenEngine::saveGameState(int slot, const Common::String &desc) { + Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving( + generateSaveName(slot)); + if (!out) + return Common::kCreatingFileFailed; + + XeenSavegameHeader header; + header._saveName = desc; + writeSavegameHeader(out, header); + + Common::Serializer s(nullptr, out); + synchronize(s); + + out->finalize(); + delete out; + + return Common::kNoError; +} + +Common::Error XeenEngine::loadGameState(int slot) { + Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading( + generateSaveName(slot)); + if (!saveFile) + return Common::kReadingFailed; + + Common::Serializer s(saveFile, nullptr); + + // Load the savaegame header + XeenSavegameHeader header; + if (!readSavegameHeader(saveFile, header)) + error("Invalid savegame"); + + if (header._thumbnail) { + header._thumbnail->free(); + delete header._thumbnail; + } + + // Load most of the savegame data + synchronize(s); + delete saveFile; + + return Common::kNoError; +} + +Common::String XeenEngine::generateSaveName(int slot) { + return Common::String::format("%s.%03d", _targetName.c_str(), slot); +} + +bool XeenEngine::canLoadGameStateCurrently() { + return true; +} + +bool XeenEngine::canSaveGameStateCurrently() { + return true; +} + +void XeenEngine::synchronize(Common::Serializer &s) { + // TODO +} + +const char *const SAVEGAME_STR = "XEEN"; +#define SAVEGAME_STR_SIZE 6 + +bool XeenEngine::readSavegameHeader(Common::InSaveFile *in, XeenSavegameHeader &header) { + char saveIdentBuffer[SAVEGAME_STR_SIZE + 1]; + header._thumbnail = nullptr; + + // Validate the header Id + in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1); + if (strncmp(saveIdentBuffer, SAVEGAME_STR, SAVEGAME_STR_SIZE)) + return false; + + header._version = in->readByte(); + if (header._version > XEEN_SAVEGAME_VERSION) + return false; + + // Read in the string + header._saveName.clear(); + char ch; + while ((ch = (char)in->readByte()) != '\0') + header._saveName += ch; + + // Get the thumbnail + header._thumbnail = Graphics::loadThumbnail(*in); + if (!header._thumbnail) + return false; + + // Read in save date/time + header._year = in->readSint16LE(); + header._month = in->readSint16LE(); + header._day = in->readSint16LE(); + header._hour = in->readSint16LE(); + header._minute = in->readSint16LE(); + header._totalFrames = in->readUint32LE(); + + return true; +} + +void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeader &header) { + // Write out a savegame header + out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1); + + out->writeByte(XEEN_SAVEGAME_VERSION); + + // Write savegame name + out->writeString(header._saveName); + out->writeByte('\0'); + + // Write a thumbnail of the screen +/* + uint8 thumbPalette[768]; + _screen->getPalette(thumbPalette); + Graphics::Surface saveThumb; + ::createThumbnail(&saveThumb, (const byte *)_screen->getPixels(), + _screen->w, _screen->h, thumbPalette); + Graphics::saveThumbnail(*out, saveThumb); + saveThumb.free(); +*/ + // Write out the save date/time + TimeDate td; + g_system->getTimeAndDate(td); + out->writeSint16LE(td.tm_year + 1900); + out->writeSint16LE(td.tm_mon + 1); + out->writeSint16LE(td.tm_mday); + out->writeSint16LE(td.tm_hour); + out->writeSint16LE(td.tm_min); +// out->writeUint32LE(_events->getFrameCounter()); +} + +void XeenEngine::playGame() { + // TODO +} + +} // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h new file mode 100644 index 0000000000..2566c1b1eb --- /dev/null +++ b/engines/xeen/xeen.h @@ -0,0 +1,153 @@ +/* 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 XEEN_XEEN_H +#define XEEN_XEEN_H + +#include "common/scummsys.h" +#include "common/system.h" +#include "common/error.h" +#include "common/random.h" +#include "common/savefile.h" +#include "common/serializer.h" +#include "common/util.h" +#include "engines/engine.h" +#include "graphics/surface.h" +#include "xeen/debugger.h" + +/** + * This is the namespace of the Xeen engine. + * + * Status of this engine: In Development + * + * Games using this engine: + * - Might & Magic 4: Clouds of Xeen + * - Might & Magic 5: Dark Side of Xeen + * - Might & Magic: World of Xeen + * - Might & Magic: Swords of Xeen + */ +namespace Xeen { + +enum { + GType_Clouds = 1, + GType_Dark = 2, + GType_World = 3, + GType_Swords = 4 +}; + +enum XeenDebugChannels { + kDebugPath = 1 << 0, + kDebugScripts = 1 << 1, + kDebugGraphics = 1 << 2, + kDebugSound = 1 << 3 +}; + +struct XeenGameDescription; + +#define XEEN_SAVEGAME_VERSION 1 +#define GAME_FRAME_TIME 50 + +struct XeenSavegameHeader { + uint8 _version; + Common::String _saveName; + Graphics::Surface *_thumbnail; + int _year, _month, _day; + int _hour, _minute; + int _totalFrames; +}; + +class XeenEngine : public Engine { +private: + const XeenGameDescription *_gameDescription; + Common::RandomSource _randomSource; + int _loadSaveSlot; +private: + void initialize(); + + /** + * Play the game + */ + void playGame(); + + /** + * Synchronize savegame data + */ + void synchronize(Common::Serializer &s); + + /** + * Support method that generates a savegame name + * @param slot Slot number + */ + Common::String generateSaveName(int slot); + + // Engine APIs + virtual Common::Error run(); + virtual bool hasFeature(EngineFeature f) const; +public: + Debugger *_debugger; +public: + XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); + virtual ~XeenEngine(); + + uint32 getFeatures() const; + Common::Language getLanguage() const; + Common::Platform getPlatform() const; + uint16 getVersion() const; + uint32 getGameID() const; + uint32 getGameFeatures() const; + + int getRandomNumber(int maxNumber); + + /** + * Load a savegame + */ + virtual Common::Error loadGameState(int slot); + + /** + * Save the game + */ + virtual Common::Error saveGameState(int slot, const Common::String &desc); + + /** + * Returns true if a savegame can currently be loaded + */ + bool canLoadGameStateCurrently(); + + /** + * Returns true if the game can currently be saved + */ + bool canSaveGameStateCurrently(); + + /** + * Read in a savegame header + */ + static bool readSavegameHeader(Common::InSaveFile *in, XeenSavegameHeader &header); + + /** + * Write out a savegame header + */ + void writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeader &header); +}; + +} // End of namespace Xeen + +#endif /* XEEN_XEEN_H */ -- cgit v1.2.3 From 977a25ec35d63fab0db315b35a69a4a508f587e9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 24 Dec 2014 09:58:47 +1100 Subject: XEEN: Implemented resource manager --- engines/xeen/module.mk | 2 + engines/xeen/resources.cpp | 214 +++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/resources.h | 64 ++++++++++++++ engines/xeen/xeen.cpp | 4 + 4 files changed, 284 insertions(+) create mode 100644 engines/xeen/resources.cpp create mode 100644 engines/xeen/resources.h (limited to 'engines/xeen') diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index a33b26a988..d129d10efe 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -1,7 +1,9 @@ MODULE := engines/xeen MODULE_OBJS := \ + debugger.o \ detection.o \ + resources.o \ xeen.o # This module can be built as a plugin diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp new file mode 100644 index 0000000000..f99be12c3d --- /dev/null +++ b/engines/xeen/resources.cpp @@ -0,0 +1,214 @@ +/* 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/scummsys.h" +#include "common/archive.h" +#include "common/memstream.h" +#include "common/textconsole.h" +#include "xeen/xeen.h" +#include "xeen/resources.h" + +namespace Xeen { + +/** + * Xeen CC file implementation + */ +class CCArchive : public Common::Archive { +private: + /** + * Details of a single entry in a CC file index + */ + struct CCEntry { + uint16 _id; + uint32 _offset; + uint16 _size; + + CCEntry() : _id(0), _offset(0), _size(0) {} + CCEntry(uint16 id, uint32 offset, uint32 size) + : _id(id), _offset(offset), _size(size) { + } + }; + + Common::Array<CCEntry> _index; + Common::String _filename; + + uint16 convertNameToId(const Common::String &resourceName) const; + + void loadIndex(Common::SeekableReadStream *stream); + + bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const; +public: + CCArchive(const Common::String &filename); + virtual ~CCArchive(); + + // Archive implementation + virtual bool hasFile(const Common::String &name) const; + virtual int listMembers(Common::ArchiveMemberList &list) const; + virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const; + virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; +}; + +CCArchive::CCArchive(const Common::String &filename): _filename(filename) { + File f(filename); + loadIndex(&f); +} + +CCArchive::~CCArchive() { +} + +// Archive implementation +bool CCArchive::hasFile(const Common::String &name) const { + CCEntry ccEntry; + return getHeaderEntry(name, ccEntry); +} + +int CCArchive::listMembers(Common::ArchiveMemberList &list) const { + // CC files don't maintain the original filenames, so we can't list it + return 0; +} + +const Common::ArchiveMemberPtr CCArchive::getMember(const Common::String &name) const { + if (!hasFile(name)) + return Common::ArchiveMemberPtr(); + + return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this)); +} + +Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::String &name) const { + CCEntry ccEntry; + + if (getHeaderEntry(name, ccEntry)) { + // Open the correct CC file + Common::File f; + if (!f.open(_filename)) + error("Could not open CC file"); + + // Read in the data for the specific resource + f.seek(ccEntry._offset); + byte *data = new byte[ccEntry._size]; + f.read(data, ccEntry._size); + + // Decrypt the data + for (int i = 0; i < ccEntry._size; ++i) + data[i] ^= 0x35; + + // Return the data as a stream + return new Common::MemoryReadStream(data, ccEntry._size, DisposeAfterUse::YES); + } + + return nullptr; +} + +/** + * Hash a given filename to produce the Id that represents it + */ +uint16 CCArchive::convertNameToId(const Common::String &resourceName) const { + if (resourceName.empty()) + return 0xffff; + + Common::String name = resourceName; + name.toUppercase(); + + const byte *msgP = (const byte *)name.c_str(); + int total = *msgP++; + for (; *msgP; total += *msgP++) { + // Rotate the bits in 'total' right 7 places + total = (total & 0x007F) << 9 | (total & 0xFF80) >> 7; + } + + return total; +} + +/** + * Load the index of a given CC file + */ +void CCArchive::loadIndex(Common::SeekableReadStream *stream) { + int count = stream->readUint16LE(); + + // Read in the data for the archive's index + byte *rawIndex = new byte[count * 8]; + stream->read(rawIndex, count * 8); + + // Decrypt the index + int ah = 0xac; + for (int i = 0; i < count * 8; ++i) { + rawIndex[i] = (byte)(((rawIndex[i] << 2 | rawIndex[i] >> 6) + ah) & 0xff); + ah += 0x67; + } + + // Extract the index data into entry structures + _index.reserve(count); + const byte *entryP = &rawIndex[0]; + for (int i = 0; i < count; ++i, entryP += 8) { + CCEntry entry; + entry._id = READ_LE_UINT16(entryP); + entry._offset = READ_LE_UINT32(entryP + 2) & 0xffffff; + entry._size = READ_LE_UINT16(entryP + 5); + assert(!entryP[7]); + + _index.push_back(entry); + } + + delete[] rawIndex; +} + +/** +* Given a resource name, returns whether an entry exists, and returns +* the header index data for that entry +*/ +bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const { + uint16 id = convertNameToId(resourceName); + + // Loop through the index + for (uint i = 0; i < _index.size(); ++i) { + if (_index[i]._id == id) { + ccEntry = _index[i]; + return true; + } + } + + // Could not find an entry + return false; +} + +/*------------------------------------------------------------------------*/ + +void Resources::init(XeenEngine *vm) { + Common::File f; + + const char *ARCHIVES[3] = { "xeen", "dark", "intro" }; + for (int i = 0; i < 3; ++i) { + Common::String filename = Common::String::format("%s.cc", ARCHIVES[i]); + if (f.exists(filename)) { + SearchMan.add(ARCHIVES[i], new CCArchive(filename)); + } + } +} + +/*------------------------------------------------------------------------*/ + +void File::openFile(const Common::String &filename) { + if (!Common::File::open(filename)) + error("Could not open file - %s", filename.c_str()); +} + +} // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h new file mode 100644 index 0000000000..61b6310874 --- /dev/null +++ b/engines/xeen/resources.h @@ -0,0 +1,64 @@ +/* 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 XEEN_RESOURCES_H +#define XEEN_RESOURCES_H + +#include "common/scummsys.h" +#include "common/file.h" + +namespace Xeen { + +class XeenEngine; + +class Resources { +public: + /** + * Instantiates the resource manager + */ + static void init(XeenEngine *vm); +}; + +/** + * Derived file class + */ +class File : public Common::File { +public: + /** + * Constructor + */ + File() : Common::File() {} + + /** + * Constructor + */ + File(const Common::String &filename) { openFile(filename); } + + /** + * Opens the given file, throwing an error if it can't be opened + */ + void openFile(const Common::String &filename); +}; + +} // End of namespace MADS + +#endif /* MADS_RESOURCES_H */ diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 3fe75e10a0..12871fda91 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -28,6 +28,7 @@ #include "graphics/scaler.h" #include "graphics/thumbnail.h" #include "xeen/xeen.h" +#include "xeen/resources.h" namespace Xeen { @@ -49,6 +50,7 @@ void XeenEngine::initialize() { // Create sub-objects of the engine _debugger = new Debugger(this); + Resources::init(this); // Set graphics mode initGraphics(320, 200, false); @@ -204,6 +206,8 @@ void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeade void XeenEngine::playGame() { // TODO + // Test resource manager + File f("FNT"); } } // End of namespace Xeen -- cgit v1.2.3 From a8da12bbe4684183cbe4d5c6ac480af2515d07cf Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 25 Dec 2014 17:02:51 +1100 Subject: XEEN: Added skeletons for Clouds, Dark Side, and World of Xeen engines --- engines/xeen/clouds/clouds_game.cpp | 38 ++++++++++++++++++++++++ engines/xeen/clouds/clouds_game.h | 42 +++++++++++++++++++++++++++ engines/xeen/darkside/darkside_game.cpp | 38 ++++++++++++++++++++++++ engines/xeen/darkside/darkside_game.h | 42 +++++++++++++++++++++++++++ engines/xeen/detection.cpp | 21 +++++++++++++- engines/xeen/detection_tables.h | 2 +- engines/xeen/module.mk | 3 ++ engines/xeen/worldofxeen/worldofxeen_game.cpp | 36 +++++++++++++++++++++++ engines/xeen/worldofxeen/worldofxeen_game.h | 41 ++++++++++++++++++++++++++ engines/xeen/xeen.cpp | 3 -- engines/xeen/xeen.h | 12 ++++---- 11 files changed, 267 insertions(+), 11 deletions(-) create mode 100644 engines/xeen/clouds/clouds_game.cpp create mode 100644 engines/xeen/clouds/clouds_game.h create mode 100644 engines/xeen/darkside/darkside_game.cpp create mode 100644 engines/xeen/darkside/darkside_game.h create mode 100644 engines/xeen/worldofxeen/worldofxeen_game.cpp create mode 100644 engines/xeen/worldofxeen/worldofxeen_game.h (limited to 'engines/xeen') diff --git a/engines/xeen/clouds/clouds_game.cpp b/engines/xeen/clouds/clouds_game.cpp new file mode 100644 index 0000000000..4987ce05dd --- /dev/null +++ b/engines/xeen/clouds/clouds_game.cpp @@ -0,0 +1,38 @@ +/* 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 "xeen/clouds/clouds_game.h" + +namespace Xeen { + +CloudsEngine::CloudsEngine(OSystem *syst, const XeenGameDescription *gameDesc) + : XeenEngine(syst, gameDesc) { +} + +void CloudsEngine::playGame() { + cloudsIntro(); +} + +void CloudsEngine::cloudsIntro() { +} + +} // End of namespace Xeen diff --git a/engines/xeen/clouds/clouds_game.h b/engines/xeen/clouds/clouds_game.h new file mode 100644 index 0000000000..a8c4fbea3b --- /dev/null +++ b/engines/xeen/clouds/clouds_game.h @@ -0,0 +1,42 @@ +/* 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 XEEN_CLOUDS_GAME_H +#define XEEN_CLOUDS_GAME_H + +#include "xeen/xeen.h" + +namespace Xeen { + +class CloudsEngine : virtual public XeenEngine { +protected: + void cloudsIntro(); + + virtual void playGame(); +public: + CloudsEngine(OSystem *syst, const XeenGameDescription *gameDesc); + virtual ~CloudsEngine() {} +}; + +} // End of namespace Xeen + +#endif /* XEEN_CLOUDS_GAME_H */ diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp new file mode 100644 index 0000000000..bc0d156f7f --- /dev/null +++ b/engines/xeen/darkside/darkside_game.cpp @@ -0,0 +1,38 @@ +/* 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 "xeen/darkside/darkside_game.h" + +namespace Xeen { + +DarkSideEngine::DarkSideEngine(OSystem *syst, const XeenGameDescription *gameDesc) + : XeenEngine(syst, gameDesc) { +} + +void DarkSideEngine::playGame() { + playGame(); +} + +void DarkSideEngine::darkSideIntro() { +} + +} // End of namespace Xeen diff --git a/engines/xeen/darkside/darkside_game.h b/engines/xeen/darkside/darkside_game.h new file mode 100644 index 0000000000..827ba2088d --- /dev/null +++ b/engines/xeen/darkside/darkside_game.h @@ -0,0 +1,42 @@ +/* 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 XEEN_DARKSIDE_GAME_H +#define XEEN_DARKSIDE_GAME_H + +#include "xeen/xeen.h" + +namespace Xeen { + +class DarkSideEngine : virtual public XeenEngine { +protected: + void darkSideIntro(); + + virtual void playGame(); +public: + DarkSideEngine(OSystem *syst, const XeenGameDescription *gameDesc); + virtual ~DarkSideEngine() {} +}; + +} // End of namespace Xeen + +#endif /* XEEN_DARKSIDE_GAME_H */ diff --git a/engines/xeen/detection.cpp b/engines/xeen/detection.cpp index 2b30478808..3bd4c22f97 100644 --- a/engines/xeen/detection.cpp +++ b/engines/xeen/detection.cpp @@ -21,6 +21,9 @@ */ #include "xeen/xeen.h" +#include "xeen/clouds/clouds_game.h" +#include "xeen/darkside/darkside_game.h" +#include "xeen/worldofxeen/worldofxeen_game.h" #include "base/plugins.h" #include "common/savefile.h" @@ -62,6 +65,8 @@ Common::Platform XeenEngine::getPlatform() const { static const PlainGameDescriptor XeenGames[] = { { "xeen", "Xeen" }, + { "clouds", "Clouds of Xeen" }, + { "darkside", "Dark Side of Xeen" }, { "worldofxeen", "World of Xeen" }, {0, 0} }; @@ -108,7 +113,21 @@ bool Xeen::XeenEngine::hasFeature(EngineFeature f) const { bool XeenMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { const Xeen::XeenGameDescription *gd = (const Xeen::XeenGameDescription *)desc; - *engine = new Xeen::XeenEngine(syst, gd); + + switch (gd->gameID) { + case Xeen::GType_Clouds: + *engine = new Xeen::CloudsEngine(syst, gd); + break; + case Xeen::GType_DarkSide: + *engine = new Xeen::DarkSideEngine(syst, gd); + break; + case Xeen::GType_WorldOfXeen: + *engine = new Xeen::WorldOfXeenEngine(syst, gd); + break; + default: + break; + } + return gd != 0; } diff --git a/engines/xeen/detection_tables.h b/engines/xeen/detection_tables.h index e106abf8cd..0735daa507 100644 --- a/engines/xeen/detection_tables.h +++ b/engines/xeen/detection_tables.h @@ -38,7 +38,7 @@ static const XeenGameDescription gameDescriptions[] = { ADGF_NO_FLAGS, GUIO1(GUIO_NONE) }, - GType_World, + GType_WorldOfXeen, 0 }, diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index d129d10efe..b02d26d58c 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -1,6 +1,9 @@ MODULE := engines/xeen MODULE_OBJS := \ + clouds\clouds_game.o \ + darkside\darkside_game.o \ + worldofxeen\worldofxeen_game.o \ debugger.o \ detection.o \ resources.o \ diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp new file mode 100644 index 0000000000..f27b8b9380 --- /dev/null +++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp @@ -0,0 +1,36 @@ +/* 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 "xeen/worldofxeen/worldofxeen_game.h" + +namespace Xeen { + +WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) + : CloudsEngine(syst, gameDesc), DarkSideEngine(syst, gameDesc), + XeenEngine(syst, gameDesc) { +} + +void WorldOfXeenEngine::playGame () { + darkSideIntro(); +} + +} // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/worldofxeen_game.h b/engines/xeen/worldofxeen/worldofxeen_game.h new file mode 100644 index 0000000000..7227e11fc4 --- /dev/null +++ b/engines/xeen/worldofxeen/worldofxeen_game.h @@ -0,0 +1,41 @@ +/* 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 XEEN_WORLDOFXEEN_GAME_H +#define XEEN_WORLDOFXEEN_GAME_H + +#include "xeen/clouds/clouds_game.h" +#include "xeen/darkside/darkside_game.h" + +namespace Xeen { + +class WorldOfXeenEngine : public DarkSideEngine, CloudsEngine { +protected: + virtual void playGame(); +public: + WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); + virtual ~WorldOfXeenEngine() {} +}; + +} // End of namespace Xeen + +#endif /* XEEN_WORLDOFXEEN_GAME_H */ diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 12871fda91..73f0c24d9f 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -205,9 +205,6 @@ void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeade } void XeenEngine::playGame() { - // TODO - // Test resource manager - File f("FNT"); } } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 2566c1b1eb..e5122ce147 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -49,8 +49,8 @@ namespace Xeen { enum { GType_Clouds = 1, - GType_Dark = 2, - GType_World = 3, + GType_DarkSide = 2, + GType_WorldOfXeen = 3, GType_Swords = 4 }; @@ -80,13 +80,13 @@ private: const XeenGameDescription *_gameDescription; Common::RandomSource _randomSource; int _loadSaveSlot; -private: - void initialize(); - +protected: /** * Play the game */ - void playGame(); + virtual void playGame(); +private: + void initialize(); /** * Synchronize savegame data -- cgit v1.2.3 From a933e661a93a0bf3466ba2dabc2f8d36e3587c5d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 25 Dec 2014 19:29:38 +1100 Subject: XEEN: Added skeleton events manager and screen class --- engines/xeen/debugger.cpp | 2 +- engines/xeen/events.cpp | 113 ++++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/events.h | 66 +++++++++++++++++++++++++++ engines/xeen/module.mk | 2 + engines/xeen/screen.cpp | 38 ++++++++++++++++ engines/xeen/screen.h | 45 ++++++++++++++++++ engines/xeen/xeen.cpp | 6 +++ engines/xeen/xeen.h | 4 ++ 8 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 engines/xeen/events.cpp create mode 100644 engines/xeen/events.h create mode 100644 engines/xeen/screen.cpp create mode 100644 engines/xeen/screen.h (limited to 'engines/xeen') diff --git a/engines/xeen/debugger.cpp b/engines/xeen/debugger.cpp index 0642498749..aa4516e3bc 100644 --- a/engines/xeen/debugger.cpp +++ b/engines/xeen/debugger.cpp @@ -53,4 +53,4 @@ bool Debugger::Cmd_LoadScene(int argc, const char **argv) { return true; } -} // End of namespace Access +} // End of namespace Xeen diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp new file mode 100644 index 0000000000..e75744eb01 --- /dev/null +++ b/engines/xeen/events.cpp @@ -0,0 +1,113 @@ +/* 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/scummsys.h" +#include "graphics/cursorman.h" +#include "common/events.h" +#include "common/endian.h" +#include "engines/util.h" +#include "xeen/xeen.h" +#include "xeen/events.h" +#include "xeen/screen.h" + +namespace Xeen { + +/** + * Constructor + */ +EventsManager::EventsManager(XeenEngine *vm) : _vm(vm) { + _frameCounter = 0; + _priorFrameCounterTime = 0; + _gameCounter = 0; + _priorGameCounterTime = 0; +} + +/** + * Destructor + */ +EventsManager::~EventsManager() { +} + +/** + * Show the mouse cursor + */ +void EventsManager::showCursor() { + CursorMan.showMouse(true); +} + +/** + * Hide the mouse cursor + */ +void EventsManager::hideCursor() { + CursorMan.showMouse(false); +} + +/** + * Returns if the mouse cursor is visible + */ +bool EventsManager::isCursorVisible() { + return CursorMan.isVisible(); +} + +void EventsManager::pollEvents() { + uint32 timer = g_system->getMillis(); + if (timer >= (_priorFrameCounterTime + GAME_FRAME_TIME)) { + _priorFrameCounterTime = timer; + nextFrame(); + } + + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_QUIT: + case Common::EVENT_RTL: + return; + default: + break; + } + } +} + +/** + * Updates the game counter to match the current frame counter + */ +void EventsManager::updateGameCounter() { + _gameCounter = _frameCounter; +} + +/** + * Returns the number of frames elapsed since the last call to + * updateGameCounter() + */ +uint32 EventsManager::timeElapsed() { + return _frameCounter - _gameCounter; +} + +/** + * Handles moving to the next game frame + */ +void EventsManager::nextFrame() { + ++_frameCounter; + _vm->_screen->update(); +} + +} // End of namespace Xeen diff --git a/engines/xeen/events.h b/engines/xeen/events.h new file mode 100644 index 0000000000..637d710364 --- /dev/null +++ b/engines/xeen/events.h @@ -0,0 +1,66 @@ +/* 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 XEEN_EVENTS_H +#define XEEN_EVENTS_H + +#include "common/scummsys.h" +#include "common/events.h" + +namespace Xeen { + +#define GAME_FRAME_RATE (1000 / 18.2) + +class XeenEngine; + +class EventsManager { +private: + XeenEngine *_vm; + uint32 _frameCounter; + uint32 _priorFrameCounterTime; + uint32 _gameCounter; + uint32 _priorGameCounterTime; + + void nextFrame(); +public: + EventsManager(XeenEngine *vm); + + ~EventsManager(); + + uint32 getFrameCounter() { return _frameCounter; } + + void showCursor(); + + void hideCursor(); + + bool isCursorVisible(); + + void pollEvents(); + + void updateGameCounter(); + + uint32 timeElapsed(); +}; + +} // End of namespace Xeen + +#endif /* XEEN_EVENTS_H */ diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index b02d26d58c..3b4529e73f 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -6,7 +6,9 @@ MODULE_OBJS := \ worldofxeen\worldofxeen_game.o \ debugger.o \ detection.o \ + events.o \ resources.o \ + screen.o \ xeen.o # This module can be built as a plugin diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp new file mode 100644 index 0000000000..d17e01063d --- /dev/null +++ b/engines/xeen/screen.cpp @@ -0,0 +1,38 @@ +/* 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 "xeen/screen.h" + +namespace Xeen { + +/** + * Constructor + */ +Screen::Screen(XeenEngine *vm) : _vm(vm) { +} + +void Screen::update() { + g_system->copyRectToScreen(getPixels(), pitch, 0, 0, w, h); + g_system->updateScreen(); +} + +} // End of namespace Xeen diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h new file mode 100644 index 0000000000..94dce60de9 --- /dev/null +++ b/engines/xeen/screen.h @@ -0,0 +1,45 @@ +/* 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 XEEN_SCREEN_H +#define XEEN_SCREEN_H + +#include "common/scummsys.h" +#include "common/system.h" +#include "graphics/surface.h" + +namespace Xeen { + +class XeenEngine; + +class Screen: public Graphics::Surface { +private: + XeenEngine *_vm; +public: + Screen(XeenEngine *vm); + + void update(); +}; + +} // End of namespace Xeen + +#endif /* XEEN_SCREEN_H */ diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 73f0c24d9f..cf60aa4555 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -35,10 +35,14 @@ namespace Xeen { XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) : _gameDescription(gameDesc), Engine(syst), _randomSource("Xeen") { _debugger = nullptr; + _events = nullptr; + _screen = nullptr; } XeenEngine::~XeenEngine() { delete _debugger; + delete _events; + delete _screen; } void XeenEngine::initialize() { @@ -50,6 +54,8 @@ void XeenEngine::initialize() { // Create sub-objects of the engine _debugger = new Debugger(this); + _events = new EventsManager(this); + _screen = new Screen(this); Resources::init(this); // Set graphics mode diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index e5122ce147..dba340e329 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -33,6 +33,8 @@ #include "engines/engine.h" #include "graphics/surface.h" #include "xeen/debugger.h" +#include "xeen/events.h" +#include "xeen/screen.h" /** * This is the namespace of the Xeen engine. @@ -104,6 +106,8 @@ private: virtual bool hasFeature(EngineFeature f) const; public: Debugger *_debugger; + EventsManager *_events; + Screen *_screen; public: XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); virtual ~XeenEngine(); -- cgit v1.2.3 From 4e05f36abdbeb0a0215c0ad5e939bce9a65cf69a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 25 Dec 2014 20:56:35 +1100 Subject: XEEN: Add XSurface base class and Screen dirty rect code --- engines/xeen/module.mk | 3 +- engines/xeen/resources.cpp | 18 +++++++++++ engines/xeen/resources.h | 27 ++++++++++------- engines/xeen/screen.cpp | 67 ++++++++++++++++++++++++++++++++++++++++- engines/xeen/screen.h | 17 +++++++++-- engines/xeen/xsurface.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/xsurface.h | 51 +++++++++++++++++++++++++++++++ 7 files changed, 243 insertions(+), 15 deletions(-) create mode 100644 engines/xeen/xsurface.cpp create mode 100644 engines/xeen/xsurface.h (limited to 'engines/xeen') diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 3b4529e73f..c036376e93 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -9,7 +9,8 @@ MODULE_OBJS := \ events.o \ resources.o \ screen.o \ - xeen.o + xeen.o \ + xsurface.o # This module can be built as a plugin ifeq ($(ENABLE_XEEN), DYNAMIC_PLUGIN) diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index f99be12c3d..e9c31e337f 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -206,9 +206,27 @@ void Resources::init(XeenEngine *vm) { /*------------------------------------------------------------------------*/ +/** + * Opens the given file, throwing an error if it can't be opened + */ void File::openFile(const Common::String &filename) { if (!Common::File::open(filename)) error("Could not open file - %s", filename.c_str()); } +/*------------------------------------------------------------------------*/ + +SpriteResource::SpriteResource(const Common::String &filename) { + +} + +int SpriteResource::size() const { + return _frames.size(); +} + +const XSurface &SpriteResource::getFrame(int frame) { + return _frames[frame]; +} + + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 61b6310874..4cf5212af4 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -24,7 +24,10 @@ #define XEEN_RESOURCES_H #include "common/scummsys.h" +#include "common/array.h" #include "common/file.h" +#include "graphics/surface.h" +#include "xeen/xsurface.h" namespace Xeen { @@ -43,22 +46,24 @@ public: */ class File : public Common::File { public: - /** - * Constructor - */ File() : Common::File() {} - - /** - * Constructor - */ File(const Common::String &filename) { openFile(filename); } + virtual ~File() {} - /** - * Opens the given file, throwing an error if it can't be opened - */ void openFile(const Common::String &filename); }; -} // End of namespace MADS +class SpriteResource { +private: + Common::Array<XSurface> _frames; +public: + SpriteResource(const Common::String &filename); + + int size() const; + + const XSurface &getFrame(int frame); +}; + +} // End of namespace Xeen #endif /* MADS_RESOURCES_H */ diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index d17e01063d..038222bfe2 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -31,8 +31,73 @@ Screen::Screen(XeenEngine *vm) : _vm(vm) { } void Screen::update() { - g_system->copyRectToScreen(getPixels(), pitch, 0, 0, w, h); + // Merge the dirty rects + mergeDirtyRects(); + + // Loop through copying dirty areas to the physical screen + Common::List<Common::Rect>::iterator i; + for (i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) { + const Common::Rect &r = *i; + const byte *srcP = (const byte *)getBasePtr(r.left, r.top); + g_system->copyRectToScreen(srcP, this->pitch, r.left, r.top, + r.width(), r.height()); + } + + // Signal the physical screen to update g_system->updateScreen(); + _dirtyRects.clear(); +} + +void Screen::addDirtyRect(const Common::Rect &r) { + _dirtyRects.push_back(r); +} + +void Screen::transBlitFrom(const XSurface &src, const Common::Point &destPos) { + XSurface::transBlitFrom(src, destPos); + addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + src.w, destPos.y + src.h)); +} + +void Screen::blitFrom(const XSurface &src, const Common::Point &destPos) { + XSurface::blitFrom(src, destPos); + addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + src.w, destPos.y + src.h)); +} + +void Screen::mergeDirtyRects() { + Common::List<Common::Rect>::iterator rOuter, rInner; + + // Ensure dirty rect list has at least two entries + rOuter = _dirtyRects.begin(); + for (int i = 0; i < 2; ++i, ++rOuter) { + if (rOuter == _dirtyRects.end()) + return; + } + + // Process the dirty rect list to find any rects to merge + for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) { + rInner = rOuter; + while (++rInner != _dirtyRects.end()) { + + if ((*rOuter).intersects(*rInner)) { + // these two rectangles overlap or + // are next to each other - merge them + + unionRectangle(*rOuter, *rOuter, *rInner); + + // remove the inner rect from the list + _dirtyRects.erase(rInner); + + // move back to beginning of list + rInner = rOuter; + } + } + } +} + +bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) { + destRect = src1; + destRect.extend(src2); + + return !destRect.isEmpty(); } } // End of namespace Xeen diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 94dce60de9..491b702ded 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -25,19 +25,32 @@ #include "common/scummsys.h" #include "common/system.h" -#include "graphics/surface.h" +#include "common/array.h" +#include "common/rect.h" +#include "xeen/xsurface.h" namespace Xeen { class XeenEngine; -class Screen: public Graphics::Surface { +class Screen: public XSurface { private: XeenEngine *_vm; + Common::List<Common::Rect> _dirtyRects; + + void mergeDirtyRects(); + + bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2); +public: + virtual void transBlitFrom(const XSurface &src, const Common::Point &destPos); + + virtual void blitFrom(const XSurface &src, const Common::Point &destPos); public: Screen(XeenEngine *vm); void update(); + + void addDirtyRect(const Common::Rect &r); }; } // End of namespace Xeen diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp new file mode 100644 index 0000000000..4ab8cf6331 --- /dev/null +++ b/engines/xeen/xsurface.cpp @@ -0,0 +1,75 @@ +/* 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 "xeen/xsurface.h" + +namespace Xeen { + +XSurface::XSurface(): Graphics::Surface() { +} + +XSurface::XSurface(int w, int h) : Graphics::Surface() { + create(w, h); +} + +void XSurface::create(uint16 w, uint16 h) { + Graphics::Surface::create(w, h, Graphics::PixelFormat::createFormatCLUT8()); +} + +void XSurface::transBlitFrom(const XSurface &src) { + transBlitFrom(src, Common::Point()); +} + +void XSurface::blitFrom(const XSurface &src) { + blitFrom(src, Common::Point()); +} + +void XSurface::transBlitFrom(const XSurface &src, const Common::Point &destPos) { + if (getPixels() == nullptr) + create(w, h); + + for (int yp = 0; yp < src.h; ++yp) { + const byte *srcP = (const byte *)src.getBasePtr(0, yp); + byte *destP = (byte *)getBasePtr(destPos.x, destPos.y + yp); + + for (int xp = 0; xp < this->w; ++xp, ++srcP, ++destP) { + if (*srcP != 0) + *destP = *srcP; + } + } +} + +void XSurface::blitFrom(const XSurface &src, const Common::Point &destPos) { + if (getPixels() == nullptr) + create(w, h); + + for (int yp = 0; yp < src.h; ++yp) { + const byte *srcP = (const byte *)src.getBasePtr(0, yp); + byte *destP = (byte *)getBasePtr(destPos.x, destPos.y + yp); + + for (int xp = 0; xp < this->w; ++xp, ++srcP, ++destP) { + *destP = *srcP; + } + } +} + +} // End of namespace Xeen diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h new file mode 100644 index 0000000000..e547bd9139 --- /dev/null +++ b/engines/xeen/xsurface.h @@ -0,0 +1,51 @@ +/* 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 XEEN_XSURFACE_H +#define XEEN_XSURFACE_H + +#include "common/scummsys.h" +#include "common/system.h" +#include "common/rect.h" +#include "graphics/surface.h" + +namespace Xeen { + +class XSurface: public Graphics::Surface { +public: + virtual void transBlitFrom(const XSurface &src, const Common::Point &destPos); + + virtual void blitFrom(const XSurface &src, const Common::Point &destPos); +public: + XSurface(); + XSurface(int w, int h); + + void create(uint16 w, uint16 h); + + void transBlitFrom(const XSurface &src); + + void blitFrom(const XSurface &src); +}; + +} // End of namespace Xeen + +#endif /* XEEN_XSURFACE_H */ -- cgit v1.2.3 From 42afa00392372b68013a871e90857dc151ae7c2f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 26 Dec 2014 10:05:51 +1100 Subject: XEEN: Initial implementation of sprite resource class --- engines/xeen/resources.cpp | 139 +++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/resources.h | 4 ++ engines/xeen/xsurface.cpp | 4 ++ engines/xeen/xsurface.h | 1 + 4 files changed, 148 insertions(+) (limited to 'engines/xeen') diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index e9c31e337f..3a1994da4e 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -217,7 +217,25 @@ void File::openFile(const Common::String &filename) { /*------------------------------------------------------------------------*/ SpriteResource::SpriteResource(const Common::String &filename) { + File f(filename); + // Read in the index + int count = f.readUint16LE(); + Common::Array<uint32> index; + index.resize(count); + for (int i = 0; i < count; ++i) + index[i] = f.readUint32LE(); + + // Process each shape + _frames.resize(count); + for (int i = 0; i < count; ++i) { + uint16 cell1 = index[i] & 0xffff, cell2 = index[i] >> 16; + assert(cell1); + + setFrameSize(f, cell1, cell2, _frames[i]); + decodeFrame(f, cell1, _frames[i]); + decodeFrame(f, cell2, _frames[i]); + } } int SpriteResource::size() const { @@ -228,5 +246,126 @@ const XSurface &SpriteResource::getFrame(int frame) { return _frames[frame]; } +void SpriteResource::setFrameSize(File &f, uint16 offset1, uint16 offset2, XSurface &s) { + int maxWidth = 0, maxHeight = 0; + + // Check each of the two cells for the frame for their sizes + for (int i = 0; i < 2; ++i) { + uint16 offset = (i == 0) ? offset1 : offset2; + if (!offset) + break; + + // Get the cell dimensions + f.seek(offset); + int x = f.readUint16LE(); + int w = f.readUint16LE(); + int y = f.readUint16LE(); + int h = f.readUint16LE(); + + // Check for total size of the frame + if ((x + w) > maxWidth) + maxWidth = x + w; + if ((y + h) > maxHeight) + maxHeight = x + h; + } + + // Create the surface + s.create(maxWidth, maxHeight); + + // Empty the surface + s.fillRect(Common::Rect(0, 0, maxWidth, maxHeight), 0); +} + +void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) { + // Get cell header + f.seek(offset); + int xOffset = f.readUint16LE(); + int width = f.readUint16LE(); + int yOffset = f.readUint16LE(); + int height = f.readUint16LE(); + + // The pattern steps used in the pattern command + const int patternSteps[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 }; + + // Main loop + int byteCount, opr1, opr2; + int32 pos; + for (int yPos = yOffset, byteCount = 0; yPos < height + yOffset; yPos++, byteCount = 0) { + // The number of bytes in this scan line + int lineLength = f.readByte(); + + if (lineLength == 0) { + // Skip the specified number of scan lines + yPos += f.readByte(); + } else { + // Skip the transparent color at the beginning of the scan line + int xPos = f.readByte() + xOffset; ++byteCount; + byte *destP = (byte *)s.getBasePtr(xPos, yPos); + + while (byteCount < lineLength) { + // The next byte is an opcode that determines what + // operators are to follow and how to interpret them. + int opcode = f.readByte(); ++byteCount; + + // Decode the opcode + int len = opcode & 0x1F; + int cmd = (opcode & 0xE0) >> 5; + + switch (cmd) { + case 0: // The following len + 1 bytes are stored as indexes into the color table. + case 1: // The following len + 33 bytes are stored as indexes into the color table. + for (int i = 0; i < opcode + 1; ++i, ++xPos) + *destP++ = f.readByte(); ++byteCount; + break; + + case 2: // The following byte is an index into the color table, draw it len + 3 times. + opr1 = f.readByte(); ++byteCount; + for (int i = 0; i < len + 3; ++i, ++xPos) + *destP++ = opr1; + break; + + case 3: // Stream copy command. + opr1 = f.readUint16LE(); byteCount += 2; + pos = f.pos(); + f.seek(-opr1, SEEK_CUR); + + for (int i = 0; i < len + 4; ++i, ++xPos) + *destP++ = f.readByte(); + + f.seek(pos, SEEK_SET); + break; + + case 4: // The following two bytes are indexes into the color table, draw the pair len + 2 times. + opr1 = f.readByte(); ++byteCount; + opr2 = f.readByte(); ++byteCount; + for (int i = 0; i < len + 2; ++i, xPos += 2) { + *destP++ = opr1; + *destP++ = opr2; + } + break; + + case 5: // Skip len + 1 pixels filling them with the transparent color. + xPos += len + 1; + break; + + case 6: // Pattern command. + case 7: + // The pattern command has a different opcode format + len = opcode & 0x07; + cmd = (opcode >> 2) & 0x0E; + + opr1 = f.readByte(); ++byteCount; + for (int i = 0; i < len + 3; ++i, ++xPos) { + *destP++ = opr1; + opr1 += patternSteps[cmd + (i % 2)]; + } + break; + default: + break; + } + } + } + } +} } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 4cf5212af4..1c55cc8889 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -56,6 +56,10 @@ public: class SpriteResource { private: Common::Array<XSurface> _frames; + + void setFrameSize(File &f, uint16 offset1, uint16 offset2, XSurface &s); + + void decodeFrame(File &f, uint16 offset, XSurface &s); public: SpriteResource(const Common::String &filename); diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp index 4ab8cf6331..b5f08f4603 100644 --- a/engines/xeen/xsurface.cpp +++ b/engines/xeen/xsurface.cpp @@ -31,6 +31,10 @@ XSurface::XSurface(int w, int h) : Graphics::Surface() { create(w, h); } +XSurface::~XSurface() { + free(); +} + void XSurface::create(uint16 w, uint16 h) { Graphics::Surface::create(w, h, Graphics::PixelFormat::createFormatCLUT8()); } diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h index e547bd9139..7a189fac1d 100644 --- a/engines/xeen/xsurface.h +++ b/engines/xeen/xsurface.h @@ -38,6 +38,7 @@ public: public: XSurface(); XSurface(int w, int h); + ~XSurface(); void create(uint16 w, uint16 h); -- cgit v1.2.3 From 1249bc03fdbf6d1bc390f9aea45b482cbb258e33 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 26 Dec 2014 13:10:30 +1100 Subject: XEEN: Implemented horizontal and vertical page merging --- engines/xeen/darkside/darkside_game.cpp | 19 ++++++++ engines/xeen/resources.cpp | 6 +-- engines/xeen/screen.cpp | 83 +++++++++++++++++++++++++++++++++ engines/xeen/screen.h | 23 +++++++++ engines/xeen/xsurface.h | 2 + 5 files changed, 130 insertions(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp index bc0d156f7f..2e9186e42f 100644 --- a/engines/xeen/darkside/darkside_game.cpp +++ b/engines/xeen/darkside/darkside_game.cpp @@ -21,6 +21,8 @@ */ #include "xeen/darkside/darkside_game.h" +#include "xeen/resources.h" +#include "xeen/screen.h" namespace Xeen { @@ -33,6 +35,23 @@ void DarkSideEngine::playGame() { } void DarkSideEngine::darkSideIntro() { + //sub_28F40 + _screen->loadPalette("dark.pal"); + File special("special.bin"); + SpriteResource nwc[4] = { + SpriteResource("nwc1.int"), SpriteResource("nwc2.int"), + SpriteResource("nwc3.int"), SpriteResource("nwc4.int") + }; + File voc[3] = { + File("dragon1.voc"), File("dragon2.voc"), File("dragon3.voc") + }; + + _screen->loadBackground("nwc1.raw"); + _screen->loadPage(0); + _screen->loadBackground("nwc2.raw"); + _screen->loadPage(1); + + _screen->horizMerge(0); } } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 3a1994da4e..b005d7431d 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -280,7 +280,7 @@ void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) { // Get cell header f.seek(offset); int xOffset = f.readUint16LE(); - int width = f.readUint16LE(); + f.skip(2); int yOffset = f.readUint16LE(); int height = f.readUint16LE(); @@ -288,7 +288,7 @@ void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) { const int patternSteps[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 }; // Main loop - int byteCount, opr1, opr2; + int opr1, opr2; int32 pos; for (int yPos = yOffset, byteCount = 0; yPos < height + yOffset; yPos++, byteCount = 0) { // The number of bytes in this scan line @@ -298,7 +298,7 @@ void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) { // Skip the specified number of scan lines yPos += f.readByte(); } else { - // Skip the transparent color at the beginning of the scan line + // Skip the transparent pixels at the beginning of the scan line int xPos = f.readByte() + xOffset; ++byteCount; byte *destP = (byte *)s.getBasePtr(xPos, yPos); diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 038222bfe2..4783890a60 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -21,6 +21,7 @@ */ #include "xeen/screen.h" +#include "xeen/resources.h" namespace Xeen { @@ -28,6 +29,7 @@ namespace Xeen { * Constructor */ Screen::Screen(XeenEngine *vm) : _vm(vm) { + } void Screen::update() { @@ -100,4 +102,85 @@ bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, co return !destRect.isEmpty(); } +/** + * Load a palette resource into the temporary palette + */ +void Screen::loadPalette(const Common::String &name) { + File f(name); + f.read(_tempPaltte, PALETTE_SIZE); +} + +/** + * Load a background resource into memory + */ +void Screen::loadBackground(const Common::String &name) { + File f(name); + + _background.create(SCREEN_WIDTH, SCREEN_HEIGHT); + assert(f.size() == (SCREEN_WIDTH * SCREEN_HEIGHT)); + f.read((byte *)_background.getPixels(), SCREEN_WIDTH * SCREEN_HEIGHT); +} + +/** + * Copy a loaded background into a display page + */ +void Screen::loadPage(int pageNum) { + assert(pageNum == 0 || pageNum == 1); + if (_pages[0].empty()) { + _pages[0].create(SCREEN_WIDTH, SCREEN_HEIGHT); + _pages[1].create(SCREEN_WIDTH, SCREEN_HEIGHT); + } + + _pages[pageNum].blitFrom(_background); +} + +/** + * Merge the two pages along a horizontal split point + */ +void Screen::horizMerge(int xp) { + if (_pages[0].empty()) + return; + + for (int y = 0; y < SCREEN_HEIGHT; ++y) { + byte *destP = (byte *)_background.getBasePtr(0, y); + const byte *srcP = (const byte *)_pages[0].getBasePtr(0, y); + Common::copy(srcP, srcP + SCREEN_WIDTH - xp, destP); + + if (xp != 0) { + srcP = (const byte *)_pages[1].getBasePtr(xp, y); + Common::copy(srcP, srcP + SCREEN_WIDTH - xp, destP + xp); + } + } +} + +/** + * Merge the two pages along a vertical split point + */ +void Screen::vertMerge(int yp) { + if (_pages[0].empty()) + return; + + for (int y = 0; y < SCREEN_HEIGHT - yp; ++y) { + const byte *srcP = (const byte *)_pages[0].getBasePtr(0, y); + byte *destP = (byte *)_background.getBasePtr(0, y); + Common::copy(srcP, srcP + SCREEN_WIDTH, destP); + } + + for (int y = yp; y < SCREEN_HEIGHT; ++y) { + const byte *srcP = (const byte *)_pages[1].getBasePtr(0, y); + byte *destP = (byte *)_background.getBasePtr(0, y); + Common::copy(srcP, srcP + SCREEN_WIDTH, destP); + } +} + +void Screen::draw(void *data) { + // TODO: Figure out data structure that can be passed to method + assert(!data); + drawBackground(); +} + +void Screen::drawBackground() { + +} + } // End of namespace Xeen diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 491b702ded..645c4da4c7 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -31,16 +31,27 @@ namespace Xeen { +#define SCREEN_WIDTH 320 +#define SCREEN_HEIGHT 200 +#define PALETTE_COUNT 256 +#define PALETTE_SIZE (256 * 3) + class XeenEngine; class Screen: public XSurface { private: XeenEngine *_vm; Common::List<Common::Rect> _dirtyRects; + byte _mainPalette[PALETTE_SIZE]; + byte _tempPaltte[PALETTE_SIZE]; + XSurface _background; + XSurface _pages[2]; void mergeDirtyRects(); bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2); + + void drawBackground(); public: virtual void transBlitFrom(const XSurface &src, const Common::Point &destPos); @@ -51,6 +62,18 @@ public: void update(); void addDirtyRect(const Common::Rect &r); + + void loadPalette(const Common::String &name); + + void loadBackground(const Common::String &name); + + void loadPage(int pageNum); + + void horizMerge(int xp); + + void vertMerge(int yp); + + void draw(void *data); }; } // End of namespace Xeen diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h index 7a189fac1d..c2d6e78d8d 100644 --- a/engines/xeen/xsurface.h +++ b/engines/xeen/xsurface.h @@ -45,6 +45,8 @@ public: void transBlitFrom(const XSurface &src); void blitFrom(const XSurface &src); + + bool empty() const { return getPixels() == nullptr; } }; } // End of namespace Xeen -- cgit v1.2.3 From 4f423c74b701b4dceff680259d174acb6a450b76 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 26 Dec 2014 14:37:20 +1100 Subject: XEEN: Implement beginnings of Dark Side intro and supporting methods --- engines/xeen/darkside/darkside_game.cpp | 41 +++++++++++++++++++++ engines/xeen/events.cpp | 27 ++++++++++++++ engines/xeen/events.h | 8 +++++ engines/xeen/module.mk | 1 + engines/xeen/screen.cpp | 63 ++++++++++++++++++++++++++++----- engines/xeen/screen.h | 16 +++++++-- engines/xeen/sound.cpp | 34 ++++++++++++++++++ engines/xeen/sound.h | 43 ++++++++++++++++++++++ engines/xeen/xeen.cpp | 3 ++ engines/xeen/xeen.h | 2 ++ 10 files changed, 226 insertions(+), 12 deletions(-) create mode 100644 engines/xeen/sound.cpp create mode 100644 engines/xeen/sound.h (limited to 'engines/xeen') diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp index 2e9186e42f..728e15595f 100644 --- a/engines/xeen/darkside/darkside_game.cpp +++ b/engines/xeen/darkside/darkside_game.cpp @@ -46,12 +46,53 @@ void DarkSideEngine::darkSideIntro() { File("dragon1.voc"), File("dragon2.voc"), File("dragon3.voc") }; + // Load backgrounds _screen->loadBackground("nwc1.raw"); _screen->loadPage(0); _screen->loadBackground("nwc2.raw"); _screen->loadPage(1); + // Draw the screen and fade it in _screen->horizMerge(0); + _screen->draw(); + _screen->fade(4); + + bool breakFlag = false; + int nwcIndex = 0, nwcFrame = 0; + for (int idx = 0; idx < 55 && !shouldQuit(); ++idx) { + _events->updateGameCounter(); + _screen->vertMerge(0); + const XSurface &frame = nwc[nwcIndex].getFrame(nwcFrame); + _screen->transBlitFrom(frame, Common::Point(0, 0)); + _screen->draw(); + + switch (idx) { + case 17: + _sound->proc2(voc[0]); + break; + case 34: + case 44: + ++nwcIndex; + ++nwcFrame; + break; + case 35: + _sound->proc2(voc[1]); + break; + default: + ++nwcFrame; + } + + while (!shouldQuit() && _events->timeElapsed() < 2) { + _events->pollEventsAndWait(); + Common::KeyState keyState; + if (_events->getKey(keyState)) { + if (keyState.keycode == Common::KEYCODE_ESCAPE) + breakFlag = true; + } + } + } + + } } // End of namespace Xeen diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp index e75744eb01..c4adabc433 100644 --- a/engines/xeen/events.cpp +++ b/engines/xeen/events.cpp @@ -39,6 +39,8 @@ EventsManager::EventsManager(XeenEngine *vm) : _vm(vm) { _priorFrameCounterTime = 0; _gameCounter = 0; _priorGameCounterTime = 0; + _keyCode = Common::KEYCODE_INVALID; + _leftButton = _rightButton = false; } /** @@ -81,12 +83,37 @@ void EventsManager::pollEvents() { case Common::EVENT_QUIT: case Common::EVENT_RTL: return; + case Common::EVENT_KEYDOWN: + _keyCode = event.kbd.keycode; + break; default: break; } } } +void EventsManager::pollEventsAndWait() { + pollEvents(); + g_system->delayMillis(10); +} + +void EventsManager::clearEvents() { + _keyCode = Common::KEYCODE_INVALID; + _leftButton = _rightButton = false; + +} + + +bool EventsManager::getKey(Common::KeyState &key) { + if (_keyCode == Common::KEYCODE_INVALID) { + return false; + } else { + key = _keyCode; + _keyCode = Common::KEYCODE_INVALID; + return true; + } +} + /** * Updates the game counter to match the current frame counter */ diff --git a/engines/xeen/events.h b/engines/xeen/events.h index 637d710364..4d775ac758 100644 --- a/engines/xeen/events.h +++ b/engines/xeen/events.h @@ -39,6 +39,8 @@ private: uint32 _priorFrameCounterTime; uint32 _gameCounter; uint32 _priorGameCounterTime; + Common::KeyCode _keyCode; + bool _leftButton, _rightButton; void nextFrame(); public: @@ -56,6 +58,12 @@ public: void pollEvents(); + void pollEventsAndWait(); + + void clearEvents(); + + bool getKey(Common::KeyState &key); + void updateGameCounter(); uint32 timeElapsed(); diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index c036376e93..aafe9b4c22 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -9,6 +9,7 @@ MODULE_OBJS := \ events.o \ resources.o \ screen.o \ + sound.o \ xeen.o \ xsurface.o diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 4783890a60..65f9600220 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -20,8 +20,11 @@ * */ +#include "common/system.h" +#include "graphics/palette.h" #include "xeen/screen.h" #include "xeen/resources.h" +#include "xeen/xeen.h" namespace Xeen { @@ -29,7 +32,7 @@ namespace Xeen { * Constructor */ Screen::Screen(XeenEngine *vm) : _vm(vm) { - + _fadeMode = false; } void Screen::update() { @@ -116,9 +119,8 @@ void Screen::loadPalette(const Common::String &name) { void Screen::loadBackground(const Common::String &name) { File f(name); - _background.create(SCREEN_WIDTH, SCREEN_HEIGHT); assert(f.size() == (SCREEN_WIDTH * SCREEN_HEIGHT)); - f.read((byte *)_background.getPixels(), SCREEN_WIDTH * SCREEN_HEIGHT); + f.read((byte *)getPixels(), SCREEN_WIDTH * SCREEN_HEIGHT); } /** @@ -131,7 +133,7 @@ void Screen::loadPage(int pageNum) { _pages[1].create(SCREEN_WIDTH, SCREEN_HEIGHT); } - _pages[pageNum].blitFrom(_background); + _pages[pageNum].blitFrom(*this); } /** @@ -142,7 +144,7 @@ void Screen::horizMerge(int xp) { return; for (int y = 0; y < SCREEN_HEIGHT; ++y) { - byte *destP = (byte *)_background.getBasePtr(0, y); + byte *destP = (byte *)getBasePtr(0, y); const byte *srcP = (const byte *)_pages[0].getBasePtr(0, y); Common::copy(srcP, srcP + SCREEN_WIDTH - xp, destP); @@ -162,13 +164,13 @@ void Screen::vertMerge(int yp) { for (int y = 0; y < SCREEN_HEIGHT - yp; ++y) { const byte *srcP = (const byte *)_pages[0].getBasePtr(0, y); - byte *destP = (byte *)_background.getBasePtr(0, y); + byte *destP = (byte *)getBasePtr(0, y); Common::copy(srcP, srcP + SCREEN_WIDTH, destP); } for (int y = yp; y < SCREEN_HEIGHT; ++y) { const byte *srcP = (const byte *)_pages[1].getBasePtr(0, y); - byte *destP = (byte *)_background.getBasePtr(0, y); + byte *destP = (byte *)getBasePtr(0, y); Common::copy(srcP, srcP + SCREEN_WIDTH, destP); } } @@ -176,11 +178,54 @@ void Screen::vertMerge(int yp) { void Screen::draw(void *data) { // TODO: Figure out data structure that can be passed to method assert(!data); - drawBackground(); + drawScreen(); +} + +/** + * Mark the entire screen for drawing + */ +void Screen::drawScreen() { + addDirtyRect(Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); +} + +void Screen::fade(int step) { + _fadeMode = true; + fadeInner(step); +} + +void Screen::fade2(int step) { + _fadeMode = false; + fadeInner(step); } -void Screen::drawBackground() { +void Screen::fadeInner(int step) { + for (int idx = 128; idx != 0 && !_vm->shouldQuit(); idx -= step) { + int val = idx; + bool flag = !_fadeMode; + if (!flag) { + val = -(val - 128); + flag = step != 0x81; + } + + if (!flag) { + step = 0x80; + } else { + // Create a scaled palette from the temporary one + for (int i = 0; i < PALETTE_SIZE; ++i) { + _mainPalette[i] = (_tempPaltte[i] * val * 2) >> 8; + } + + updatePalette(); + } + } +} + +void Screen::updatePalette() { + updatePalette(_mainPalette, 0, 16); +} +void Screen::updatePalette(const byte *pal, int start, int count16) { + g_system->getPaletteManager()->setPalette(pal, start, count16 * 16); } } // End of namespace Xeen diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 645c4da4c7..3359af8336 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -44,14 +44,20 @@ private: Common::List<Common::Rect> _dirtyRects; byte _mainPalette[PALETTE_SIZE]; byte _tempPaltte[PALETTE_SIZE]; - XSurface _background; XSurface _pages[2]; + bool _fadeMode; void mergeDirtyRects(); bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2); - void drawBackground(); + void drawScreen(); + + void fadeInner(int step); + + void updatePalette(); + + void updatePalette(const byte *pal, int start, int count16); public: virtual void transBlitFrom(const XSurface &src, const Common::Point &destPos); @@ -73,7 +79,11 @@ public: void vertMerge(int yp); - void draw(void *data); + void draw(void *data = nullptr); + + void fade(int step); + + void fade2(int step); }; } // End of namespace Xeen diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp new file mode 100644 index 0000000000..2863a3d564 --- /dev/null +++ b/engines/xeen/sound.cpp @@ -0,0 +1,34 @@ +/* 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 "xeen/sound.h" + +namespace Xeen { + +SoundManager::SoundManager(XeenEngine *vm): _vm(vm) { +} + +void SoundManager::proc2(File &f) { + +} + +} // End of namespace Xeen diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h new file mode 100644 index 0000000000..2e163e7cce --- /dev/null +++ b/engines/xeen/sound.h @@ -0,0 +1,43 @@ +/* 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 XEEN_SOUND_H +#define XEEN_SOUND_H + +#include "common/scummsys.h" +#include "common/system.h" +#include "xeen/resources.h" + +namespace Xeen { + +class SoundManager { +private: + XeenEngine *_vm; +public: + SoundManager(XeenEngine *vm); + + void proc2(File &f); +}; + +} // End of namespace Xeen + +#endif /* XEEN_SOUND_H */ diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index cf60aa4555..f1330f5b0e 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -37,12 +37,14 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _debugger = nullptr; _events = nullptr; _screen = nullptr; + _sound = nullptr; } XeenEngine::~XeenEngine() { delete _debugger; delete _events; delete _screen; + delete _sound; } void XeenEngine::initialize() { @@ -56,6 +58,7 @@ void XeenEngine::initialize() { _debugger = new Debugger(this); _events = new EventsManager(this); _screen = new Screen(this); + _sound = new SoundManager(this); Resources::init(this); // Set graphics mode diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index dba340e329..df53b784fc 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -35,6 +35,7 @@ #include "xeen/debugger.h" #include "xeen/events.h" #include "xeen/screen.h" +#include "xeen/sound.h" /** * This is the namespace of the Xeen engine. @@ -108,6 +109,7 @@ public: Debugger *_debugger; EventsManager *_events; Screen *_screen; + SoundManager *_sound; public: XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); virtual ~XeenEngine(); -- cgit v1.2.3 From d213db3dc1b24e281e03dc593f21925db8fcd10e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 26 Dec 2014 18:31:05 +1100 Subject: XEEN: Converted SpriteResource to decoding sprite frames on the fly --- engines/xeen/darkside/darkside_game.cpp | 7 +-- engines/xeen/resources.cpp | 79 +++++++++++++-------------------- engines/xeen/resources.h | 14 ++++-- engines/xeen/screen.cpp | 18 +++----- engines/xeen/screen.h | 6 +-- engines/xeen/xsurface.cpp | 43 +++++++++--------- engines/xeen/xsurface.h | 12 ++--- 7 files changed, 79 insertions(+), 100 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp index 728e15595f..a597ab2ce8 100644 --- a/engines/xeen/darkside/darkside_game.cpp +++ b/engines/xeen/darkside/darkside_game.cpp @@ -59,11 +59,10 @@ void DarkSideEngine::darkSideIntro() { bool breakFlag = false; int nwcIndex = 0, nwcFrame = 0; - for (int idx = 0; idx < 55 && !shouldQuit(); ++idx) { + for (int idx = 0; idx < 55 && !shouldQuit() && !breakFlag; ++idx) { _events->updateGameCounter(); _screen->vertMerge(0); - const XSurface &frame = nwc[nwcIndex].getFrame(nwcFrame); - _screen->transBlitFrom(frame, Common::Point(0, 0)); + nwc[nwcIndex].draw(*_screen, nwcFrame, Common::Point(0, 0)); _screen->draw(); switch (idx) { @@ -91,8 +90,6 @@ void DarkSideEngine::darkSideIntro() { } } } - - } } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index b005d7431d..4cc586f014 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -217,70 +217,45 @@ void File::openFile(const Common::String &filename) { /*------------------------------------------------------------------------*/ SpriteResource::SpriteResource(const Common::String &filename) { + // Open the resource File f(filename); // Read in the index int count = f.readUint16LE(); - Common::Array<uint32> index; - index.resize(count); - for (int i = 0; i < count; ++i) - index[i] = f.readUint32LE(); - - // Process each shape - _frames.resize(count); - for (int i = 0; i < count; ++i) { - uint16 cell1 = index[i] & 0xffff, cell2 = index[i] >> 16; - assert(cell1); + _index.resize(count); - setFrameSize(f, cell1, cell2, _frames[i]); - decodeFrame(f, cell1, _frames[i]); - decodeFrame(f, cell2, _frames[i]); + for (int i = 0; i < count; ++i) { + _index[i]._offset1 = f.readUint16LE(); + _index[i]._offset2 = f.readUint16LE(); } -} -int SpriteResource::size() const { - return _frames.size(); + // Read in a copy of the file + _filesize = f.size(); + _data = new byte[_filesize]; + f.seek(0); + f.read(_data, _filesize); } -const XSurface &SpriteResource::getFrame(int frame) { - return _frames[frame]; +SpriteResource::~SpriteResource() { + delete[] _data; } -void SpriteResource::setFrameSize(File &f, uint16 offset1, uint16 offset2, XSurface &s) { - int maxWidth = 0, maxHeight = 0; - - // Check each of the two cells for the frame for their sizes - for (int i = 0; i < 2; ++i) { - uint16 offset = (i == 0) ? offset1 : offset2; - if (!offset) - break; - - // Get the cell dimensions - f.seek(offset); - int x = f.readUint16LE(); - int w = f.readUint16LE(); - int y = f.readUint16LE(); - int h = f.readUint16LE(); - - // Check for total size of the frame - if ((x + w) > maxWidth) - maxWidth = x + w; - if ((y + h) > maxHeight) - maxHeight = x + h; - } +int SpriteResource::size() const { + return _index.size(); +} - // Create the surface - s.create(maxWidth, maxHeight); - - // Empty the surface - s.fillRect(Common::Rect(0, 0, maxWidth, maxHeight), 0); +void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const { + drawOffset(dest, _index[frame]._offset1, destPos); + if (_index[frame]._offset2) + drawOffset(dest, _index[frame]._offset2, destPos); } -void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) { +void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const { // Get cell header + Common::MemoryReadStream f(_data, _filesize); f.seek(offset); int xOffset = f.readUint16LE(); - f.skip(2); + int width = f.readUint16LE(); int yOffset = f.readUint16LE(); int height = f.readUint16LE(); @@ -300,7 +275,7 @@ void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) { } else { // Skip the transparent pixels at the beginning of the scan line int xPos = f.readByte() + xOffset; ++byteCount; - byte *destP = (byte *)s.getBasePtr(xPos, yPos); + byte *destP = (byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos); while (byteCount < lineLength) { // The next byte is an opcode that determines what @@ -314,8 +289,9 @@ void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) { switch (cmd) { case 0: // The following len + 1 bytes are stored as indexes into the color table. case 1: // The following len + 33 bytes are stored as indexes into the color table. - for (int i = 0; i < opcode + 1; ++i, ++xPos) + for (int i = 0; i < opcode + 1; ++i, ++xPos) { *destP++ = f.readByte(); ++byteCount; + } break; case 2: // The following byte is an index into the color table, draw it len + 3 times. @@ -364,8 +340,13 @@ void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) { break; } } + + assert(byteCount == lineLength); } } + + dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, + destPos.x + xOffset + width, destPos.y + yOffset + height)); } } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 1c55cc8889..fcb184277a 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -55,17 +55,23 @@ public: class SpriteResource { private: - Common::Array<XSurface> _frames; + struct IndexEntry { + uint16 _offset1, _offset2; + }; + Common::Array<IndexEntry> _index; - void setFrameSize(File &f, uint16 offset1, uint16 offset2, XSurface &s); + int32 _filesize; + byte *_data; - void decodeFrame(File &f, uint16 offset, XSurface &s); + void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const; public: SpriteResource(const Common::String &filename); + ~SpriteResource(); + int size() const; - const XSurface &getFrame(int frame); + void draw(XSurface &dest, int frame, const Common::Point &destPos) const; }; } // End of namespace Xeen diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 65f9600220..0c7df8b776 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -33,6 +33,7 @@ namespace Xeen { */ Screen::Screen(XeenEngine *vm) : _vm(vm) { _fadeMode = false; + create(SCREEN_WIDTH, SCREEN_HEIGHT); } void Screen::update() { @@ -57,16 +58,6 @@ void Screen::addDirtyRect(const Common::Rect &r) { _dirtyRects.push_back(r); } -void Screen::transBlitFrom(const XSurface &src, const Common::Point &destPos) { - XSurface::transBlitFrom(src, destPos); - addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + src.w, destPos.y + src.h)); -} - -void Screen::blitFrom(const XSurface &src, const Common::Point &destPos) { - XSurface::blitFrom(src, destPos); - addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + src.w, destPos.y + src.h)); -} - void Screen::mergeDirtyRects() { Common::List<Common::Rect>::iterator rOuter, rInner; @@ -110,7 +101,8 @@ bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, co */ void Screen::loadPalette(const Common::String &name) { File f(name); - f.read(_tempPaltte, PALETTE_SIZE); + for (int i = 0; i < PALETTE_SIZE; ++i) + _tempPaltte[i] = f.readByte() << 2; } /** @@ -133,7 +125,7 @@ void Screen::loadPage(int pageNum) { _pages[1].create(SCREEN_WIDTH, SCREEN_HEIGHT); } - _pages[pageNum].blitFrom(*this); + blitTo(_pages[pageNum]); } /** @@ -217,6 +209,8 @@ void Screen::fadeInner(int step) { updatePalette(); } + + _vm->_events->pollEventsAndWait(); } } diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 3359af8336..02fe74607c 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -59,16 +59,12 @@ private: void updatePalette(const byte *pal, int start, int count16); public: - virtual void transBlitFrom(const XSurface &src, const Common::Point &destPos); - - virtual void blitFrom(const XSurface &src, const Common::Point &destPos); + virtual void addDirtyRect(const Common::Rect &r); public: Screen(XeenEngine *vm); void update(); - void addDirtyRect(const Common::Rect &r); - void loadPalette(const Common::String &name); void loadBackground(const Common::String &name); diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp index b5f08f4603..f63ad14350 100644 --- a/engines/xeen/xsurface.cpp +++ b/engines/xeen/xsurface.cpp @@ -20,6 +20,7 @@ * */ +#include "common/algorithm.h" #include "xeen/xsurface.h" namespace Xeen { @@ -39,41 +40,43 @@ void XSurface::create(uint16 w, uint16 h) { Graphics::Surface::create(w, h, Graphics::PixelFormat::createFormatCLUT8()); } -void XSurface::transBlitFrom(const XSurface &src) { - transBlitFrom(src, Common::Point()); +void XSurface::transBlitTo(XSurface &dest) const { + transBlitTo(dest, Common::Point()); } -void XSurface::blitFrom(const XSurface &src) { - blitFrom(src, Common::Point()); +void XSurface::blitTo(XSurface &dest) const { + blitTo(dest, Common::Point()); } -void XSurface::transBlitFrom(const XSurface &src, const Common::Point &destPos) { - if (getPixels() == nullptr) - create(w, h); +void XSurface::transBlitTo(XSurface &dest, const Common::Point &destPos) const { + if (dest.getPixels() == nullptr) + dest.create(w, h); - for (int yp = 0; yp < src.h; ++yp) { - const byte *srcP = (const byte *)src.getBasePtr(0, yp); - byte *destP = (byte *)getBasePtr(destPos.x, destPos.y + yp); + for (int yp = 0; yp < h; ++yp) { + const byte *srcP = (const byte *)getBasePtr(0, yp); + byte *destP = (byte *)dest.getBasePtr(destPos.x, destPos.y + yp); - for (int xp = 0; xp < this->w; ++xp, ++srcP, ++destP) { + for (int xp = 0; xp < w; ++xp, ++srcP, ++destP) { if (*srcP != 0) *destP = *srcP; } } + + dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y)); } -void XSurface::blitFrom(const XSurface &src, const Common::Point &destPos) { - if (getPixels() == nullptr) - create(w, h); +void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const { + if (dest.getPixels() == nullptr) + dest.create(w, h); - for (int yp = 0; yp < src.h; ++yp) { - const byte *srcP = (const byte *)src.getBasePtr(0, yp); - byte *destP = (byte *)getBasePtr(destPos.x, destPos.y + yp); + for (int yp = 0; yp < h; ++yp) { + const byte *srcP = (const byte *)getBasePtr(0, yp); + byte *destP = (byte *)dest.getBasePtr(destPos.x, destPos.y + yp); - for (int xp = 0; xp < this->w; ++xp, ++srcP, ++destP) { - *destP = *srcP; - } + Common::copy(srcP, srcP + w, destP); } + + dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y)); } } // End of namespace Xeen diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h index c2d6e78d8d..92f1236349 100644 --- a/engines/xeen/xsurface.h +++ b/engines/xeen/xsurface.h @@ -32,9 +32,7 @@ namespace Xeen { class XSurface: public Graphics::Surface { public: - virtual void transBlitFrom(const XSurface &src, const Common::Point &destPos); - - virtual void blitFrom(const XSurface &src, const Common::Point &destPos); + virtual void addDirtyRect(const Common::Rect &r) {} public: XSurface(); XSurface(int w, int h); @@ -42,9 +40,13 @@ public: void create(uint16 w, uint16 h); - void transBlitFrom(const XSurface &src); + void transBlitTo(XSurface &dest) const; + + void transBlitTo(XSurface &dest, const Common::Point &destPos) const; + + void blitTo(XSurface &dest, const Common::Point &destPos) const; - void blitFrom(const XSurface &src); + void blitTo(XSurface &dest) const; bool empty() const { return getPixels() == nullptr; } }; -- cgit v1.2.3 From 1a6dd88713ff6a6994f9e4d69abf8e3c66538bb2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 26 Dec 2014 18:50:14 +1100 Subject: XEEN: Fix error in vertMerge --- engines/xeen/darkside/darkside_game.cpp | 3 ++- engines/xeen/resources.cpp | 2 +- engines/xeen/screen.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp index a597ab2ce8..17a998eb41 100644 --- a/engines/xeen/darkside/darkside_game.cpp +++ b/engines/xeen/darkside/darkside_game.cpp @@ -60,6 +60,7 @@ void DarkSideEngine::darkSideIntro() { bool breakFlag = false; int nwcIndex = 0, nwcFrame = 0; for (int idx = 0; idx < 55 && !shouldQuit() && !breakFlag; ++idx) { + // Render the next frame _events->updateGameCounter(); _screen->vertMerge(0); nwc[nwcIndex].draw(*_screen, nwcFrame, Common::Point(0, 0)); @@ -72,7 +73,7 @@ void DarkSideEngine::darkSideIntro() { case 34: case 44: ++nwcIndex; - ++nwcFrame; + nwcFrame = 0; break; case 35: _sound->proc2(voc[1]); diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 4cc586f014..736f014a81 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -345,7 +345,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi } } - dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, + dest.addDirtyRect(Common::Rect(destPos.x + xOffset, destPos.y + yOffset, destPos.x + xOffset + width, destPos.y + yOffset + height)); } diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 0c7df8b776..e390f16cdd 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -160,7 +160,7 @@ void Screen::vertMerge(int yp) { Common::copy(srcP, srcP + SCREEN_WIDTH, destP); } - for (int y = yp; y < SCREEN_HEIGHT; ++y) { + for (int y = SCREEN_HEIGHT - yp; y < SCREEN_HEIGHT; ++y) { const byte *srcP = (const byte *)_pages[1].getBasePtr(0, y); byte *destP = (byte *)getBasePtr(0, y); Common::copy(srcP, srcP + SCREEN_WIDTH, destP); -- cgit v1.2.3 From cadb7176bc6336de2ee05c3465e9954157a8e4a6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 26 Dec 2014 18:57:58 +1100 Subject: XEEN: Fix error in vertMerge --- engines/xeen/screen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index e390f16cdd..5276b6971f 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -141,8 +141,8 @@ void Screen::horizMerge(int xp) { Common::copy(srcP, srcP + SCREEN_WIDTH - xp, destP); if (xp != 0) { - srcP = (const byte *)_pages[1].getBasePtr(xp, y); - Common::copy(srcP, srcP + SCREEN_WIDTH - xp, destP + xp); + srcP = (const byte *)_pages[1].getBasePtr(0, y); + Common::copy(srcP + SCREEN_WIDTH - xp, srcP + SCREEN_WIDTH, destP + SCREEN_WIDTH - xp); } } } -- cgit v1.2.3 From a93177e0b3a7aba23667b1edbf81fe4d949d69b7 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 26 Dec 2014 21:10:02 +1100 Subject: XEEN: Fix for correct line offsets in sprite drawing --- engines/xeen/resources.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/xeen') diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 736f014a81..6690ad08e0 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -322,6 +322,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi case 5: // Skip len + 1 pixels filling them with the transparent color. xPos += len + 1; + destP += len + 1; break; case 6: // Pattern command. -- cgit v1.2.3 From 1d62e224b98e4d2c9736c4965b3da5735b32c022 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 26 Dec 2014 22:00:39 +1100 Subject: XEEN: Implement button handlng and rest of Dark Side title screen --- engines/xeen/darkside/darkside_game.cpp | 66 ++++++++++++++++++++++++++++----- engines/xeen/darkside/darkside_game.h | 2 + engines/xeen/events.cpp | 33 ++++++++++++++++- engines/xeen/events.h | 6 +++ engines/xeen/resources.cpp | 5 +++ engines/xeen/resources.h | 2 + engines/xeen/sound.cpp | 5 +++ engines/xeen/sound.h | 2 + 8 files changed, 110 insertions(+), 11 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp index 17a998eb41..c067242431 100644 --- a/engines/xeen/darkside/darkside_game.cpp +++ b/engines/xeen/darkside/darkside_game.cpp @@ -35,11 +35,16 @@ void DarkSideEngine::playGame() { } void DarkSideEngine::darkSideIntro() { + showTitle(); + if (shouldQuit()) + return; +} + +void DarkSideEngine::showTitle() { //sub_28F40 _screen->loadPalette("dark.pal"); - File special("special.bin"); SpriteResource nwc[4] = { - SpriteResource("nwc1.int"), SpriteResource("nwc2.int"), + SpriteResource("nwc1.int"), SpriteResource("nwc2.int"), SpriteResource("nwc3.int"), SpriteResource("nwc4.int") }; File voc[3] = { @@ -57,13 +62,13 @@ void DarkSideEngine::darkSideIntro() { _screen->draw(); _screen->fade(4); - bool breakFlag = false; + // Initial loop for dragon roaring int nwcIndex = 0, nwcFrame = 0; - for (int idx = 0; idx < 55 && !shouldQuit() && !breakFlag; ++idx) { + for (int idx = 0; idx < 55 && !shouldQuit(); ++idx) { // Render the next frame _events->updateGameCounter(); _screen->vertMerge(0); - nwc[nwcIndex].draw(*_screen, nwcFrame, Common::Point(0, 0)); + nwc[nwcIndex].draw(*_screen, nwcFrame); _screen->draw(); switch (idx) { @@ -84,13 +89,54 @@ void DarkSideEngine::darkSideIntro() { while (!shouldQuit() && _events->timeElapsed() < 2) { _events->pollEventsAndWait(); - Common::KeyState keyState; - if (_events->getKey(keyState)) { - if (keyState.keycode == Common::KEYCODE_ESCAPE) - breakFlag = true; - } + if (_events->isKeyMousePressed()) + return; } } + + // Loop for dragon using flyspray + for (int idx = 0; idx < 42 && !shouldQuit(); ++idx) { + _events->updateGameCounter(); + _screen->vertMerge(SCREEN_HEIGHT); + nwc[3].draw(*_screen, idx); + _screen->draw(); + + switch (idx) { + case 3: + _sound->startMusic(40); + break; + case 11: + _sound->startMusic(0); + case 27: + case 30: + _sound->startMusic(3); + break; + case 31: + _sound->proc2(voc[2]); + break; + case 33: + _sound->startMusic(2); + break; + default: + break; + } + + while (!shouldQuit() && _events->timeElapsed() < 2) { + _events->pollEventsAndWait(); + if (_events->isKeyMousePressed()) + return; + } + } + + // Pause fora bit + while (!shouldQuit() && _events->timeElapsed() < 10) { + _events->pollEventsAndWait(); + if (_events->isKeyMousePressed()) + return; + } + + // TODO: Stop sound and music + } } // End of namespace Xeen diff --git a/engines/xeen/darkside/darkside_game.h b/engines/xeen/darkside/darkside_game.h index 827ba2088d..5574d459e1 100644 --- a/engines/xeen/darkside/darkside_game.h +++ b/engines/xeen/darkside/darkside_game.h @@ -28,6 +28,8 @@ namespace Xeen { class DarkSideEngine : virtual public XeenEngine { +private: + void showTitle(); protected: void darkSideIntro(); diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp index c4adabc433..8e1b207556 100644 --- a/engines/xeen/events.cpp +++ b/engines/xeen/events.cpp @@ -86,6 +86,18 @@ void EventsManager::pollEvents() { case Common::EVENT_KEYDOWN: _keyCode = event.kbd.keycode; break; + case Common::EVENT_LBUTTONDOWN: + _leftButton = true; + return; + case Common::EVENT_LBUTTONUP: + _leftButton = false; + return; + case Common::EVENT_RBUTTONDOWN: + _rightButton = true; + return; + case Common::EVENT_RBUTTONUP: + _rightButton = false; + break; default: break; } @@ -103,7 +115,11 @@ void EventsManager::clearEvents() { } - +void EventsManager::debounceMouse() { + while (_leftButton && !_vm->shouldQuit()) { + pollEventsAndWait(); + } +} bool EventsManager::getKey(Common::KeyState &key) { if (_keyCode == Common::KEYCODE_INVALID) { return false; @@ -114,6 +130,21 @@ bool EventsManager::getKey(Common::KeyState &key) { } } +bool EventsManager::isKeyPending() const { + return _keyCode != Common::KEYCODE_INVALID; +} + +/** + * Returns true if a key or mouse press is pending + */ +bool EventsManager::isKeyMousePressed() { + bool result = _leftButton || _rightButton || isKeyPending(); + debounceMouse(); + clearEvents(); + + return result; +} + /** * Updates the game counter to match the current frame counter */ diff --git a/engines/xeen/events.h b/engines/xeen/events.h index 4d775ac758..b380f7bb93 100644 --- a/engines/xeen/events.h +++ b/engines/xeen/events.h @@ -62,8 +62,14 @@ public: void clearEvents(); + void debounceMouse(); + bool getKey(Common::KeyState &key); + bool isKeyPending() const; + + bool isKeyMousePressed(); + void updateGameCounter(); uint32 timeElapsed(); diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 6690ad08e0..40353c1cdc 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -250,6 +250,11 @@ void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPo drawOffset(dest, _index[frame]._offset2, destPos); } +void SpriteResource::draw(XSurface &dest, int frame) const { + draw(dest, frame, Common::Point()); +} + + void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const { // Get cell header Common::MemoryReadStream f(_data, _filesize); diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index fcb184277a..d29f0f125c 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -72,6 +72,8 @@ public: int size() const; void draw(XSurface &dest, int frame, const Common::Point &destPos) const; + + void draw(XSurface &dest, int frame) const; }; } // End of namespace Xeen diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp index 2863a3d564..9495b25fe4 100644 --- a/engines/xeen/sound.cpp +++ b/engines/xeen/sound.cpp @@ -31,4 +31,9 @@ void SoundManager::proc2(File &f) { } +void SoundManager::startMusic(int v1) { + +} + + } // End of namespace Xeen diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index 2e163e7cce..b122fc150f 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -36,6 +36,8 @@ public: SoundManager(XeenEngine *vm); void proc2(File &f); + + void startMusic(int v1); }; } // End of namespace Xeen -- cgit v1.2.3 From 537da8b7b9090ef9be2ea9b4c3ef2b76461364ab Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 27 Dec 2014 09:07:25 +1100 Subject: XEEN: Second Dark Side title screen, beginnings of starting sequence --- engines/xeen/darkside/darkside_game.cpp | 112 +++++++++++++++++++++++++++----- engines/xeen/darkside/darkside_game.h | 8 ++- engines/xeen/screen.cpp | 32 +++++++-- engines/xeen/screen.h | 11 +++- 4 files changed, 137 insertions(+), 26 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp index c067242431..3dd4c0ea30 100644 --- a/engines/xeen/darkside/darkside_game.cpp +++ b/engines/xeen/darkside/darkside_game.cpp @@ -34,13 +34,31 @@ void DarkSideEngine::playGame() { playGame(); } +bool DarkSideEngine::pause(int amount) { + while (!shouldQuit() && _events->timeElapsed() < amount) { + _events->pollEventsAndWait(); + if (_events->isKeyMousePressed()) + return true; + } + + return shouldQuit(); +} + void DarkSideEngine::darkSideIntro() { - showTitle(); + showTitle1(); if (shouldQuit()) return; + + showTitle2(); + if (shouldQuit()) + return; + + // TODO: Only show startup if not seen before + showStartSequence(); } -void DarkSideEngine::showTitle() { +void DarkSideEngine::showTitle1() { + // TODO: Starting method, and sound //sub_28F40 _screen->loadPalette("dark.pal"); SpriteResource nwc[4] = { @@ -87,11 +105,8 @@ void DarkSideEngine::showTitle() { ++nwcFrame; } - while (!shouldQuit() && _events->timeElapsed() < 2) { - _events->pollEventsAndWait(); - if (_events->isKeyMousePressed()) - return; - } + if (pause(2)) + return; } // Loop for dragon using flyspray @@ -121,22 +136,87 @@ void DarkSideEngine::showTitle() { break; } - while (!shouldQuit() && _events->timeElapsed() < 2) { + if (pause(2)) + return; + } + + // Pause for a bit + pause(10); +} + +void DarkSideEngine::showTitle2() { + _screen->fadeOut(8); + //TODO: Stuff + + _screen->loadBackground("jvc.raw"); + _screen->draw(); + _screen->fade(4); + + _events->updateGameCounter(); + pause(60); +} + +void DarkSideEngine::showStartSequence() { + _screen->fadeOut(8); + _screen->loadBackground("pyramid2.raw"); + _screen->loadPage(0); + _screen->loadPage(1); + _screen->loadBackground("pyramid3.raw"); + _screen->saveScreen(1); + + SpriteResource sprites[3] = { + SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int") + }; + File voc[2] = { + File("pharoh1a.voc"), File("pharoh1b.voc") + }; + + _screen->vertMerge(SCREEN_HEIGHT); + _screen->loadPage(0); + _screen->loadPage(1); + + int yp = 0; + int frame = 0; + int idx1 = 0; + bool skipElapsed = false; + uint32 timeExpired = 0; + bool fadeFlag = true; + + for (int idx = 200; idx > 0; ) { + _events->updateGameCounter(); + _screen->vertMerge(yp); + + sprites[0].draw(*_screen, 0); + if (frame) + sprites[0].draw(*_screen, frame); + + idx1 = (idx1 + 1) % 4; + if (!idx1) + frame = (frame + 1) % 10; + + _screen->draw(); + if (!skipElapsed) { + timeExpired = MAX(_events->timeElapsed(), (uint32)1); + skipElapsed = true; + } + + idx -= timeExpired; + frame = MIN(frame + timeExpired, (uint)200); + + while (_events->timeElapsed() < 1) { _events->pollEventsAndWait(); if (_events->isKeyMousePressed()) return; } } - // Pause fora bit - while (!shouldQuit() && _events->timeElapsed() < 10) { - _events->pollEventsAndWait(); - if (_events->isKeyMousePressed()) - return; - } - - // TODO: Stop sound and music + _screen->vertMerge(SCREEN_HEIGHT); + _screen->saveScreen(1); + _screen->draw(); + _screen->freePages(); + _events->updateGameCounter(); + pause(30); } } // End of namespace Xeen diff --git a/engines/xeen/darkside/darkside_game.h b/engines/xeen/darkside/darkside_game.h index 5574d459e1..39ec87fa1c 100644 --- a/engines/xeen/darkside/darkside_game.h +++ b/engines/xeen/darkside/darkside_game.h @@ -29,7 +29,13 @@ namespace Xeen { class DarkSideEngine : virtual public XeenEngine { private: - void showTitle(); + bool pause(int amount); + + void showTitle1(); + + void showTitle2(); + + void showStartSequence(); protected: void darkSideIntro(); diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 5276b6971f..699e13e8ce 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -32,7 +32,7 @@ namespace Xeen { * Constructor */ Screen::Screen(XeenEngine *vm) : _vm(vm) { - _fadeMode = false; + _fadeIn = false; create(SCREEN_WIDTH, SCREEN_HEIGHT); } @@ -128,6 +128,11 @@ void Screen::loadPage(int pageNum) { blitTo(_pages[pageNum]); } +void Screen::freePages() { + _pages[0].free(); + _pages[1].free(); +} + /** * Merge the two pages along a horizontal split point */ @@ -181,19 +186,19 @@ void Screen::drawScreen() { } void Screen::fade(int step) { - _fadeMode = true; + _fadeIn = true; fadeInner(step); } -void Screen::fade2(int step) { - _fadeMode = false; +void Screen::fadeOut(int step) { + _fadeIn = false; fadeInner(step); } void Screen::fadeInner(int step) { - for (int idx = 128; idx != 0 && !_vm->shouldQuit(); idx -= step) { - int val = idx; - bool flag = !_fadeMode; + for (int idx = 128; idx >= 0 && !_vm->shouldQuit(); idx -= step) { + int val = MAX(idx, 0); + bool flag = !_fadeIn; if (!flag) { val = -(val - 128); flag = step != 0x81; @@ -222,4 +227,17 @@ void Screen::updatePalette(const byte *pal, int start, int count16) { g_system->getPaletteManager()->setPalette(pal, start, count16 * 16); } +void Screen::saveScreen(int slot) { + assert(slot > 0 && slot < 10); + _savedScreens[slot - 1].copyFrom(*this); +} + +void Screen::restoreScreen(int slot) { + assert(slot > 0 && slot < 10); + + _savedScreens[slot - 1].blitTo(*this); + _savedScreens[slot - 1].free(); +} + + } // End of namespace Xeen diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 02fe74607c..72d9da0437 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -45,7 +45,8 @@ private: byte _mainPalette[PALETTE_SIZE]; byte _tempPaltte[PALETTE_SIZE]; XSurface _pages[2]; - bool _fadeMode; + XSurface _savedScreens[10]; + bool _fadeIn; void mergeDirtyRects(); @@ -71,6 +72,8 @@ public: void loadPage(int pageNum); + void freePages(); + void horizMerge(int xp); void vertMerge(int yp); @@ -79,7 +82,11 @@ public: void fade(int step); - void fade2(int step); + void fadeOut(int step); + + void saveScreen(int slot); + + void restoreScreen(int slot); }; } // End of namespace Xeen -- cgit v1.2.3 From 676e7583f2d992a5a047e1e1b9f9a9d8929f2a0a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 29 Dec 2014 21:20:40 -1000 Subject: XEEN: Temporary processing of Window list data to produce formatted output --- engines/xeen/darkside/darkside_game.cpp | 15 +-- engines/xeen/darkside/darkside_game.h | 2 +- engines/xeen/screen.cpp | 172 +++++++++++++++++++++++++- engines/xeen/screen.h | 17 ++- engines/xeen/worldofxeen/worldofxeen_game.cpp | 2 +- 5 files changed, 193 insertions(+), 15 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp index 3dd4c0ea30..c039d1ff0b 100644 --- a/engines/xeen/darkside/darkside_game.cpp +++ b/engines/xeen/darkside/darkside_game.cpp @@ -31,10 +31,10 @@ DarkSideEngine::DarkSideEngine(OSystem *syst, const XeenGameDescription *gameDes } void DarkSideEngine::playGame() { - playGame(); + // TODO } -bool DarkSideEngine::pause(int amount) { +bool DarkSideEngine::pause(uint amount) { while (!shouldQuit() && _events->timeElapsed() < amount) { _events->pollEventsAndWait(); if (_events->isKeyMousePressed()) @@ -45,6 +45,7 @@ bool DarkSideEngine::pause(int amount) { } void DarkSideEngine::darkSideIntro() { + /* showTitle1(); if (shouldQuit()) return; @@ -52,7 +53,7 @@ void DarkSideEngine::darkSideIntro() { showTitle2(); if (shouldQuit()) return; - + */ // TODO: Only show startup if not seen before showStartSequence(); } @@ -78,7 +79,7 @@ void DarkSideEngine::showTitle1() { // Draw the screen and fade it in _screen->horizMerge(0); _screen->draw(); - _screen->fade(4); + _screen->fadeIn(4); // Initial loop for dragon roaring int nwcIndex = 0, nwcFrame = 0; @@ -150,7 +151,7 @@ void DarkSideEngine::showTitle2() { _screen->loadBackground("jvc.raw"); _screen->draw(); - _screen->fade(4); + _screen->fadeIn(4); _events->updateGameCounter(); pause(60); @@ -162,7 +163,7 @@ void DarkSideEngine::showStartSequence() { _screen->loadPage(0); _screen->loadPage(1); _screen->loadBackground("pyramid3.raw"); - _screen->saveScreen(1); + _screen->saveBackground(1); SpriteResource sprites[3] = { SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int") @@ -211,7 +212,7 @@ void DarkSideEngine::showStartSequence() { } _screen->vertMerge(SCREEN_HEIGHT); - _screen->saveScreen(1); + _screen->saveBackground(1); _screen->draw(); _screen->freePages(); diff --git a/engines/xeen/darkside/darkside_game.h b/engines/xeen/darkside/darkside_game.h index 39ec87fa1c..979885cc13 100644 --- a/engines/xeen/darkside/darkside_game.h +++ b/engines/xeen/darkside/darkside_game.h @@ -29,7 +29,7 @@ namespace Xeen { class DarkSideEngine : virtual public XeenEngine { private: - bool pause(int amount); + bool pause(uint amount); void showTitle1(); diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 699e13e8ce..c1b8a870c9 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -28,12 +28,178 @@ namespace Xeen { +const int WX[48] = { + 0, 237, 225, 0, + 235, 70, 52, 108, 232, 103, 226, 8, + 0, 50, 0, 50, + 228, 20, 0, 231, + 72, 99, 65, 80, + 0, 27, 15, 90, + 0, 0, 0, 50, + 12, 8, 232, 226, + 225, 27, 225, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; + + const int WY[48] = { + 0, 9, 1, 0, + 148, 20, 149, 0, + 9, 156, 0, 8, + 143, 103, 7, 71, + 106, 142, 20, 48, + 37, 59, 23, 28, + 0, 6, 15, 45, + 0, 101, 0, 112, + 11, 147, 74, 26, + 74, 6, 140, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + }; + + const int WW[48] = { + 320, 80, 94, 230, + 74, 180, 216, 92, + 80, 114, 93, 216, + 320, 216, 320, 132, + 91, 270, 320, 86, + 176, 138, 185, 176, + 320, 180, 146, 130, + 320, 320, 320, 216, + 152, 216, 80, 93, + 94, 168, 94, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + }; + +const int WH[48] = { +200, 65, 72, 149, +41, 163, 48, 200, +65, 30, 146, 132, +56, 36, 131, 58, +40, 57, 160, 93, +126, 82, 140, 120, +146, 136, 76, 112, +200, 45, 108, 36, +83, 45, 64, 120, +80, 136, 59, 0, +0, 0, 0, 0, +0, 0, 0, 0 +}; + + const int WA[48] = { + 0, 0, 1, 0, + 2, 3, 4, 5, + 0, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16, + 17, 18, 19, 20, + 21, 22, 23, 24, + 25, 26, 27, 28, + 0, 0, 29, 30, + 31, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + }; + + const int WB[48] = { + 0, 0, 8, 0, + 8, 8, 8, 0, + 0, 8, 8, 8, + 8, 8, 8, 8, + 8, 8, 8, 8, + 8, 8, 8, 8, + 8, 8, 8, 8, + 8, 8, 8, 8, + 0, 8, 8, 8, + 8, 8, 8, 8, + 8, 8, 8, 8, + 8, 8, 8, 8 + }; + + const int WXlo[48] = { 0, 237, 225, 9, + 0, 80, 0, 0, + 0, 0, 0, 8, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 99, 75, 80, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + }; + + const int WYcl[48] = { + 0, 12, 1, 8, + 0, 38, 0, 0, + 0, 0, 0, 8, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 59, 36, 28, + 0, 0, 0, 0, + 0, 101, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + }; + + const int WXhi[48] = { + 320, 307, 319, 216, + 0, 240, 0, 0, + 0, 0, 0, 224, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 237, 245, 256, + 320, 0, 0, 0, + 0, 320, 0, 0, + 52, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + }; + + const int WYch[48] = { + 200, 68, 73, 140, + 0, 166, 0, 0, + 0, 0, 0, 200, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 141, 172, + 148, 146, 0, 0, + 0, 0, 45, 0, + 0, 94, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + }; + +Window::Window(const Common::Rect &bounds, int a, int border, int xLo, int ycL, int xHi, int ycH) { + _bounds = bounds; + _a = a; + _border = border; + _xLo = xLo; + _ycL = ycL; + _xHi = xHi; + _ycH = ycH; +} + +/*------------------------------------------------------------------------*/ + /** * Constructor */ Screen::Screen(XeenEngine *vm) : _vm(vm) { _fadeIn = false; create(SCREEN_WIDTH, SCREEN_HEIGHT); + + for (int i = 0; i < 48; ++i) { + warning("Window(Common::Rect(%d, %d, %d, %d), %d, %d, %d, %d, %d, %d);", + WX[i], WY[i], WX[i] + WW[i], WY[i] + WH[i], WA[i], WB[i], WXlo[i], + WYcl[i], WXhi[i], WYch[i]); + } } void Screen::update() { @@ -185,7 +351,7 @@ void Screen::drawScreen() { addDirtyRect(Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); } -void Screen::fade(int step) { +void Screen::fadeIn(int step) { _fadeIn = true; fadeInner(step); } @@ -227,12 +393,12 @@ void Screen::updatePalette(const byte *pal, int start, int count16) { g_system->getPaletteManager()->setPalette(pal, start, count16 * 16); } -void Screen::saveScreen(int slot) { +void Screen::saveBackground(int slot) { assert(slot > 0 && slot < 10); _savedScreens[slot - 1].copyFrom(*this); } -void Screen::restoreScreen(int slot) { +void Screen::restoreBackground(int slot) { assert(slot > 0 && slot < 10); _savedScreens[slot - 1].blitTo(*this); diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 72d9da0437..157d0bc178 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -38,6 +38,17 @@ namespace Xeen { class XeenEngine; +class Window { +private: + Common::Rect _bounds; + int _a; + int _border; + int _xLo, _xHi; + int _ycL, _ycH; +public: + Window(const Common::Rect &bounds, int a, int border, int xLo, int ycL, int xHi, int ycH); +}; + class Screen: public XSurface { private: XeenEngine *_vm; @@ -80,13 +91,13 @@ public: void draw(void *data = nullptr); - void fade(int step); + void fadeIn(int step); void fadeOut(int step); - void saveScreen(int slot); + void saveBackground(int slot); - void restoreScreen(int slot); + void restoreBackground(int slot); }; } // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp index f27b8b9380..dba5612e29 100644 --- a/engines/xeen/worldofxeen/worldofxeen_game.cpp +++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp @@ -30,7 +30,7 @@ WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *g } void WorldOfXeenEngine::playGame () { - darkSideIntro(); + //darkSideIntro(); } } // End of namespace Xeen -- cgit v1.2.3 From 6a71a9f4d49c20bcebff4b91ccfbfa46e4775f10 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 29 Dec 2014 22:09:21 -1000 Subject: XEEN: Proper setup of window list --- engines/xeen/screen.cpp | 221 +++++++++++++----------------------------------- engines/xeen/screen.h | 10 ++- 2 files changed, 70 insertions(+), 161 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index c1b8a870c9..79aa733df7 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -28,162 +28,14 @@ namespace Xeen { -const int WX[48] = { - 0, 237, 225, 0, - 235, 70, 52, 108, 232, 103, 226, 8, - 0, 50, 0, 50, - 228, 20, 0, 231, - 72, 99, 65, 80, - 0, 27, 15, 90, - 0, 0, 0, 50, - 12, 8, 232, 226, - 225, 27, 225, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 -}; - - const int WY[48] = { - 0, 9, 1, 0, - 148, 20, 149, 0, - 9, 156, 0, 8, - 143, 103, 7, 71, - 106, 142, 20, 48, - 37, 59, 23, 28, - 0, 6, 15, 45, - 0, 101, 0, 112, - 11, 147, 74, 26, - 74, 6, 140, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 - }; +Window::Window() : _screen(nullptr), _a(0), _border(0), + _xLo(0), _xHi(0), _ycL(0), _ycH(0) { +} - const int WW[48] = { - 320, 80, 94, 230, - 74, 180, 216, 92, - 80, 114, 93, 216, - 320, 216, 320, 132, - 91, 270, 320, 86, - 176, 138, 185, 176, - 320, 180, 146, 130, - 320, 320, 320, 216, - 152, 216, 80, 93, - 94, 168, 94, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 - }; - -const int WH[48] = { -200, 65, 72, 149, -41, 163, 48, 200, -65, 30, 146, 132, -56, 36, 131, 58, -40, 57, 160, 93, -126, 82, 140, 120, -146, 136, 76, 112, -200, 45, 108, 36, -83, 45, 64, 120, -80, 136, 59, 0, -0, 0, 0, 0, -0, 0, 0, 0 -}; - - const int WA[48] = { - 0, 0, 1, 0, - 2, 3, 4, 5, - 0, 6, 7, 8, - 9, 10, 11, 12, - 13, 14, 15, 16, - 17, 18, 19, 20, - 21, 22, 23, 24, - 25, 26, 27, 28, - 0, 0, 29, 30, - 31, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 - }; - - const int WB[48] = { - 0, 0, 8, 0, - 8, 8, 8, 0, - 0, 8, 8, 8, - 8, 8, 8, 8, - 8, 8, 8, 8, - 8, 8, 8, 8, - 8, 8, 8, 8, - 8, 8, 8, 8, - 0, 8, 8, 8, - 8, 8, 8, 8, - 8, 8, 8, 8, - 8, 8, 8, 8 - }; - - const int WXlo[48] = { 0, 237, 225, 9, - 0, 80, 0, 0, - 0, 0, 0, 8, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 99, 75, 80, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 - }; - - const int WYcl[48] = { - 0, 12, 1, 8, - 0, 38, 0, 0, - 0, 0, 0, 8, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 59, 36, 28, - 0, 0, 0, 0, - 0, 101, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 - }; - - const int WXhi[48] = { - 320, 307, 319, 216, - 0, 240, 0, 0, - 0, 0, 0, 224, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 237, 245, 256, - 320, 0, 0, 0, - 0, 320, 0, 0, - 52, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 - }; - - const int WYch[48] = { - 200, 68, 73, 140, - 0, 166, 0, 0, - 0, 0, 0, 200, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 141, 172, - 148, 146, 0, 0, - 0, 0, 45, 0, - 0, 94, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 - }; - -Window::Window(const Common::Rect &bounds, int a, int border, int xLo, int ycL, int xHi, int ycH) { - _bounds = bounds; - _a = a; - _border = border; - _xLo = xLo; - _ycL = ycL; - _xHi = xHi; - _ycH = ycH; +Window::Window(Screen *screen, const Common::Rect &bounds, int a, int border, + int xLo, int ycL, int xHi, int ycH): + _screen(screen), _bounds(bounds), _a(a), _border(border), + _xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) { } /*------------------------------------------------------------------------*/ @@ -194,12 +46,61 @@ Window::Window(const Common::Rect &bounds, int a, int border, int xLo, int ycL, Screen::Screen(XeenEngine *vm) : _vm(vm) { _fadeIn = false; create(SCREEN_WIDTH, SCREEN_HEIGHT); + setupWindows(); +} - for (int i = 0; i < 48; ++i) { - warning("Window(Common::Rect(%d, %d, %d, %d), %d, %d, %d, %d, %d, %d);", - WX[i], WY[i], WX[i] + WW[i], WY[i] + WH[i], WA[i], WB[i], WXlo[i], - WYcl[i], WXhi[i], WYch[i]); - } +void Screen::setupWindows() { + Window windows[48] = { + Window(this, Common::Rect(0, 0, 320, 200), 0, 0, 0, 0, 320, 200), + Window(this, Common::Rect(237, 9, 317, 74), 0, 0, 237, 12, 307, 68), + Window(this, Common::Rect(225, 1, 319, 73), 1, 8, 225, 1, 319, 73), + Window(this, Common::Rect(0, 0, 230, 149), 0, 0, 9, 8, 216, 140), + Window(this, Common::Rect(235, 148, 309, 189), 2, 8, 0, 0, 0, 0), + Window(this, Common::Rect(70, 20, 250, 183), 3, 8, 80, 38, 240, 166), + Window(this, Common::Rect(52, 149, 268, 197), 4, 8, 0, 0, 0, 0), + Window(this, Common::Rect(108, 0, 200, 200), 5, 0, 0, 0, 0, 0), + Window(this, Common::Rect(232, 9, 312, 74), 0, 0, 0, 0, 0, 0), + Window(this, Common::Rect(103, 156, 217, 186), 6, 8, 0, 0, 0, 0), + Window(this, Common::Rect(226, 0, 319, 146), 7, 8, 0, 0, 0, 0), + Window(this, Common::Rect(8, 8, 224, 140), 8, 8, 8, 8, 224, 200), + Window(this, Common::Rect(0, 143, 320, 199), 9, 8, 0, 0, 0, 0), + Window(this, Common::Rect(50, 103, 266, 139), 10, 8, 0, 0, 0, 0), + Window(this, Common::Rect(0, 7, 320, 138), 11, 8, 0, 0, 0, 0), + Window(this, Common::Rect(50, 71, 182, 129), 12, 8, 0, 0, 0, 0), + Window(this, Common::Rect(228, 106, 319, 146), 13, 8, 0, 0, 0, 0), + Window(this, Common::Rect(20, 142, 290, 199), 14, 8, 0, 0, 0, 0), + Window(this, Common::Rect(0, 20, 320, 180), 15, 8, 0, 0, 0, 0), + Window(this, Common::Rect(231, 48, 317, 141), 16, 8, 0, 0, 0, 0), + Window(this, Common::Rect(72, 37, 248, 163), 17, 8, 0, 0, 0, 0), + Window(this, Common::Rect(99, 59, 237, 141), 18, 8, 99, 59, 237, 0), + Window(this, Common::Rect(65, 23, 250, 163), 19, 8, 75, 36, 245, 141), + Window(this, Common::Rect(80, 28, 256, 148), 20, 8, 80, 28, 256, 172), + Window(this, Common::Rect(0, 0, 320, 146), 21, 8, 0, 0, 320, 148), + Window(this, Common::Rect(27, 6, 207, 142), 22, 8, 0, 0, 0, 146), + Window(this, Common::Rect(15, 15, 161, 91), 23, 8, 0, 0, 0, 0), + Window(this, Common::Rect(90, 45, 220, 157), 24, 8, 0, 0, 0, 0), + Window(this, Common::Rect(0, 0, 320, 200), 25, 8, 0, 0, 0, 0), + Window(this, Common::Rect(0, 101, 320, 146), 26, 8, 0, 101, 320, 0), + Window(this, Common::Rect(0, 0, 320, 108), 27, 8, 0, 0, 0, 45), + Window(this, Common::Rect(50, 112, 266, 148), 28, 8, 0, 0, 0, 0), + Window(this, Common::Rect(12, 11, 164, 94), 0, 0, 0, 0, 52, 0), + Window(this, Common::Rect(8, 147, 224, 192), 0, 8, 0, 0, 0, 94), + Window(this, Common::Rect(232, 74, 312, 138), 29, 8, 0, 0, 0, 0), + Window(this, Common::Rect(226, 26, 319, 146), 30, 8, 0, 0, 0, 0), + Window(this, Common::Rect(225, 74, 319, 154), 31, 8, 0, 0, 0, 0), + Window(this, Common::Rect(27, 6, 195, 142), 0, 8, 0, 0, 0, 0), + Window(this, Common::Rect(225, 140, 319, 199), 0, 8, 0, 0, 0, 0), + Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0), + Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0), + Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0), + Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0), + Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0), + Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0), + Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0), + Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0) + }; + + _windows = Common::Array<Window>(windows, 48); } void Screen::update() { diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 157d0bc178..cd4608cf9c 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -37,21 +37,27 @@ namespace Xeen { #define PALETTE_SIZE (256 * 3) class XeenEngine; +class Screen; class Window { private: + Screen *_screen; Common::Rect _bounds; int _a; int _border; int _xLo, _xHi; int _ycL, _ycH; public: - Window(const Common::Rect &bounds, int a, int border, int xLo, int ycL, int xHi, int ycH); + Window(); + + Window(Screen *screen, const Common::Rect &bounds, int a, int border, + int xLo, int ycL, int xHi, int ycH); }; class Screen: public XSurface { private: XeenEngine *_vm; + Common::Array<Window> _windows; Common::List<Common::Rect> _dirtyRects; byte _mainPalette[PALETTE_SIZE]; byte _tempPaltte[PALETTE_SIZE]; @@ -59,6 +65,8 @@ private: XSurface _savedScreens[10]; bool _fadeIn; + void setupWindows(); + void mergeDirtyRects(); bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2); -- cgit v1.2.3 From 9d6de4da652b2494d37756e9d12f944cddcf18c8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 30 Dec 2014 10:22:05 -1000 Subject: XEEN: Implemented cursor display --- engines/xeen/events.cpp | 22 +++++--- engines/xeen/events.h | 4 ++ engines/xeen/resources.cpp | 80 ++++++++++++++++++--------- engines/xeen/resources.h | 42 +++++++++++--- engines/xeen/screen.cpp | 18 ++---- engines/xeen/screen.h | 1 + engines/xeen/worldofxeen/worldofxeen_game.cpp | 8 +++ engines/xeen/xeen.cpp | 2 +- 8 files changed, 123 insertions(+), 54 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp index 8e1b207556..29dde3a031 100644 --- a/engines/xeen/events.cpp +++ b/engines/xeen/events.cpp @@ -34,13 +34,11 @@ namespace Xeen { /** * Constructor */ -EventsManager::EventsManager(XeenEngine *vm) : _vm(vm) { - _frameCounter = 0; - _priorFrameCounterTime = 0; - _gameCounter = 0; - _priorGameCounterTime = 0; - _keyCode = Common::KEYCODE_INVALID; - _leftButton = _rightButton = false; +EventsManager::EventsManager(XeenEngine *vm) : _vm(vm), + _frameCounter(0), _priorFrameCounterTime(0), _gameCounter(0), + _priorGameCounterTime(0), _keyCode(Common::KEYCODE_INVALID), + _leftButton(false), _rightButton(false), + _sprites("mouse.icn") { } /** @@ -49,6 +47,16 @@ EventsManager::EventsManager(XeenEngine *vm) : _vm(vm) { EventsManager::~EventsManager() { } +/* + * Set the cursor + */ +void EventsManager::setCursor(int cursorId) { + XSurface cursor; + _sprites.draw(cursor, cursorId); + + CursorMan.replaceCursor(cursor.getPixels(), cursor.w, cursor.h, 0, 0, 0); +} + /** * Show the mouse cursor */ diff --git a/engines/xeen/events.h b/engines/xeen/events.h index b380f7bb93..3590267b66 100644 --- a/engines/xeen/events.h +++ b/engines/xeen/events.h @@ -25,6 +25,7 @@ #include "common/scummsys.h" #include "common/events.h" +#include "xeen/resources.h" namespace Xeen { @@ -41,6 +42,7 @@ private: uint32 _priorGameCounterTime; Common::KeyCode _keyCode; bool _leftButton, _rightButton; + FramesResource _sprites; void nextFrame(); public: @@ -50,6 +52,8 @@ public: uint32 getFrameCounter() { return _frameCounter; } + void setCursor(int cursorId); + void showCursor(); void hideCursor(); diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 40353c1cdc..4da84c1d38 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -216,19 +216,10 @@ void File::openFile(const Common::String &filename) { /*------------------------------------------------------------------------*/ -SpriteResource::SpriteResource(const Common::String &filename) { +GraphicResource::GraphicResource(const Common::String &filename) { // Open the resource File f(filename); - // Read in the index - int count = f.readUint16LE(); - _index.resize(count); - - for (int i = 0; i < count; ++i) { - _index[i]._offset1 = f.readUint16LE(); - _index[i]._offset2 = f.readUint16LE(); - } - // Read in a copy of the file _filesize = f.size(); _data = new byte[_filesize]; @@ -236,26 +227,15 @@ SpriteResource::SpriteResource(const Common::String &filename) { f.read(_data, _filesize); } -SpriteResource::~SpriteResource() { +GraphicResource::~GraphicResource() { delete[] _data; } -int SpriteResource::size() const { - return _index.size(); -} - -void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const { - drawOffset(dest, _index[frame]._offset1, destPos); - if (_index[frame]._offset2) - drawOffset(dest, _index[frame]._offset2, destPos); -} - -void SpriteResource::draw(XSurface &dest, int frame) const { - draw(dest, frame, Common::Point()); +int GraphicResource::size() const { + return READ_LE_UINT16(_data); } - -void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const { +void GraphicResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const { // Get cell header Common::MemoryReadStream f(_data, _filesize); f.seek(offset); @@ -264,6 +244,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi int yOffset = f.readUint16LE(); int height = f.readUint16LE(); + if (dest.w < (xOffset + width) || dest.h < (yOffset + height)) + dest.create(xOffset + width, yOffset + height); + // The pattern steps used in the pattern command const int patternSteps[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 }; @@ -355,4 +338,51 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi destPos.x + xOffset + width, destPos.y + yOffset + height)); } +/*------------------------------------------------------------------------*/ + +FramesResource::FramesResource(const Common::String &filename) : + GraphicResource(filename) { + // Read in the index + Common::MemoryReadStream f(_data, _filesize); + int count = f.readUint16LE(); + _index.resize(count); + + for (int i = 0; i < count; ++i) { + _index[i] = f.readUint32LE(); + } +} + +void FramesResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const { + drawOffset(dest, _index[frame], destPos); +} + +void FramesResource::draw(XSurface &dest, int frame) const { + draw(dest, frame, Common::Point()); +} + +/*------------------------------------------------------------------------*/ + +SpriteResource::SpriteResource(const Common::String &filename) : + GraphicResource(filename) { + // Read in the index + Common::MemoryReadStream f(_data, _filesize); + int count = f.readUint16LE(); + _index.resize(count); + + for (int i = 0; i < count; ++i) { + _index[i]._offset1 = f.readUint16LE(); + _index[i]._offset2 = f.readUint16LE(); + } +} + +void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const { + drawOffset(dest, _index[frame]._offset1, destPos); + if (_index[frame]._offset2) + drawOffset(dest, _index[frame]._offset2, destPos); +} + +void SpriteResource::draw(XSurface &dest, int frame) const { + draw(dest, frame, Common::Point()); +} + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index d29f0f125c..0476319875 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -53,23 +53,49 @@ public: void openFile(const Common::String &filename); }; -class SpriteResource { +class GraphicResource { +protected: + int32 _filesize; + byte *_data; + + void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const; +public: + GraphicResource(const Common::String &filename); + + virtual ~GraphicResource(); + + int size() const; +}; + +/** + * Defines a resource that Contains a list of singular sprite frames + */ +class FramesResource : public GraphicResource { +private: + Common::Array<uint32> _index; +public: + FramesResource(const Common::String &filename); + virtual ~FramesResource() {} + + void draw(XSurface &dest, int frame, const Common::Point &destPos) const; + + void draw(XSurface &dest, int frame) const; +}; + +/** + * Defines a resource that contains sets of two layered sprites per frame + */ +class SpriteResource : public GraphicResource { private: struct IndexEntry { uint16 _offset1, _offset2; }; Common::Array<IndexEntry> _index; - int32 _filesize; - byte *_data; - - void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const; public: SpriteResource(const Common::String &filename); - ~SpriteResource(); - - int size() const; + virtual ~SpriteResource() {} void draw(XSurface &dest, int frame, const Common::Point &destPos) const; diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 79aa733df7..b1275aaf4b 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -28,13 +28,13 @@ namespace Xeen { -Window::Window() : _screen(nullptr), _a(0), _border(0), +Window::Window() : _screen(nullptr), _enabled(false), _a(0), _border(0), _xLo(0), _xHi(0), _ycL(0), _ycH(0) { } Window::Window(Screen *screen, const Common::Rect &bounds, int a, int border, int xLo, int ycL, int xHi, int ycH): - _screen(screen), _bounds(bounds), _a(a), _border(border), + _screen(screen), _enabled(false), _bounds(bounds), _a(a), _border(border), _xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) { } @@ -50,7 +50,7 @@ Screen::Screen(XeenEngine *vm) : _vm(vm) { } void Screen::setupWindows() { - Window windows[48] = { + Window windows[40] = { Window(this, Common::Rect(0, 0, 320, 200), 0, 0, 0, 0, 320, 200), Window(this, Common::Rect(237, 9, 317, 74), 0, 0, 237, 12, 307, 68), Window(this, Common::Rect(225, 1, 319, 73), 1, 8, 225, 1, 319, 73), @@ -89,18 +89,10 @@ void Screen::setupWindows() { Window(this, Common::Rect(226, 26, 319, 146), 30, 8, 0, 0, 0, 0), Window(this, Common::Rect(225, 74, 319, 154), 31, 8, 0, 0, 0, 0), Window(this, Common::Rect(27, 6, 195, 142), 0, 8, 0, 0, 0, 0), - Window(this, Common::Rect(225, 140, 319, 199), 0, 8, 0, 0, 0, 0), - Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0), - Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0), - Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0), - Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0), - Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0), - Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0), - Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0), - Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0) + Window(this, Common::Rect(225, 140, 319, 199), 0, 8, 0, 0, 0, 0) }; - _windows = Common::Array<Window>(windows, 48); + _windows = Common::Array<Window>(windows, 40); } void Screen::update() { diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index cd4608cf9c..4178460caa 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -47,6 +47,7 @@ private: int _border; int _xLo, _xHi; int _ycL, _ycH; + bool _enabled; public: Window(); diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp index dba5612e29..8057331250 100644 --- a/engines/xeen/worldofxeen/worldofxeen_game.cpp +++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp @@ -30,7 +30,15 @@ WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *g } void WorldOfXeenEngine::playGame () { + _screen->loadPalette("mm4.pal"); + _screen->fadeIn(4); + //darkSideIntro(); + _events->setCursor(0); + _events->showCursor(); + while (!shouldQuit()) { + _events->pollEventsAndWait(); + } } } // End of namespace Xeen diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index f1330f5b0e..5a293636a9 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -55,11 +55,11 @@ void XeenEngine::initialize() { DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling"); // Create sub-objects of the engine + Resources::init(this); _debugger = new Debugger(this); _events = new EventsManager(this); _screen = new Screen(this); _sound = new SoundManager(this); - Resources::init(this); // Set graphics mode initGraphics(320, 200, false); -- cgit v1.2.3 From fb47ec9627937fe5031f20d16c175e5a12b5dfe2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 30 Dec 2014 17:28:53 -1000 Subject: XEEN: In progress implementing options/main menu --- engines/xeen/menus.cpp | 292 ++++++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/menus.h | 106 ++++++++++++++++++ engines/xeen/module.mk | 1 + engines/xeen/screen.cpp | 5 + engines/xeen/screen.h | 11 +- engines/xeen/sound.h | 4 + engines/xeen/xeen.cpp | 2 + 7 files changed, 418 insertions(+), 3 deletions(-) create mode 100644 engines/xeen/menus.cpp create mode 100644 engines/xeen/menus.h (limited to 'engines/xeen') diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp new file mode 100644 index 0000000000..4ddb85a63d --- /dev/null +++ b/engines/xeen/menus.cpp @@ -0,0 +1,292 @@ +/* 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/scummsys.h" +#include "xeen/menus.h" + +namespace Xeen { + +/** + * Saves the current list of buttons + */ +void Dialog::saveButtons() { + _savedButtons.push(_buttons); +} + +/* + * Clears the current list of defined buttons + */ +void Dialog::clearButtons() { + _buttons.clear(); +} + +void Dialog::restoreButtons() { + _buttons = _savedButtons.pop(); +} + +/*------------------------------------------------------------------------*/ + +void OptionsMenu::show(XeenEngine *vm) { + OptionsMenu *menu; + + switch (vm->getGameID()) { + case GType_Clouds: + menu = new CloudsOptionsMenu(vm); + break; + case GType_DarkSide: + menu = new DarkSideOptionsMenu(vm); + break; + case GType_WorldOfXeen: + menu = new WorldOptionsMenu(vm); + break; + default: + error("Unsupported game"); + break; + } + + menu->execute(); + delete menu; +} + +void OptionsMenu::execute() { + SpriteResource special("special.icn"); + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + + File newBright("newbrigh.m"); + _vm->_sound->playMusic(newBright); + + screen._windows[28].setBounds(Common::Rect(72, 25, 248, 175)); + + Common::String title1, title2; + startup(title1, title2); + + bool firstTime = true; + while (!_vm->shouldQuit()) { + setBackground(); + events.setCursor(0); + + if (firstTime) { + firstTime = false; + warning("TODO: Read existing save file"); + } + + for (;;) { + clearButtons(); + + showTitles1(title1); + showTitles2(); + } + } +} + +void OptionsMenu::showTitles1(const Common::String &title) { + SpriteResource titleSprites(title); + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + + int frame = 0; + while (!_vm->shouldQuit() && !events.isKeyMousePressed()) { + events.updateGameCounter(); + + frame = frame % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10); + screen.restoreBackground(); + titleSprites.draw(screen, 0); + + while (events.timeElapsed() == 0) + events.pollEventsAndWait(); + } +} + +void OptionsMenu::showTitles2() { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + SoundManager &sound = *_vm->_sound; + + File voc("elect.voc"); + SpriteResource titleSprites("title2b.raw"); + SpriteResource kludgeSprites("kludge.int"); + SpriteResource title2Sprites[8] = { + SpriteResource("title2b.int"), SpriteResource("title2c.int"), + SpriteResource("title2d.int"), SpriteResource("title2e.int"), + SpriteResource("title2f.int"), SpriteResource("title2g.int"), + SpriteResource("title2h.int"), SpriteResource("title2i.int"), + }; + + kludgeSprites.draw(screen, 0); + screen.saveBackground(); + sound.playSample(&voc, 0); + + for (int i = 0; i < 30 && !_vm->shouldQuit(); ++i) { + events.updateGameCounter(); + screen.restoreBackground(); + title2Sprites[i / 4].draw(screen, i % 4); + screen._windows[0].update(); + + if (i == 19) + sound.playSample(nullptr, 0); + + while (!_vm->shouldQuit() && events.timeElapsed() < 2) + events.pollEventsAndWait(); + } + + screen.restoreBackground(); + screen._windows[0].update(); +} + +/*------------------------------------------------------------------------*/ + +void CloudsOptionsMenu::startup(Common::String &title1, Common::String &title2) { + title1 = "title1.int"; + title2 = "title1a.int"; +} + +/** +* Draws the scroll in the background +*/ +void Dialog::doScroll(bool drawFlag, bool doFade) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + const int SCROLL_L[8] = { 29, 23, 15, 251, 245, 233, 207, 185 }; + const int SCROLL_R[8] = { 165, 171, 198, 218, 228, 245, 264, 281 }; + + saveButtons(); + clearButtons(); + screen.saveBackground(); + + // Load hand vga files + SpriteResource *hand[16]; + for (int i = 0; i < 16; ++i) { + Common::String name = Common::String::format("hand%02u.vga"); + hand[i] = new SpriteResource(name); + } + + // Load marb vga files + SpriteResource *marb[5]; + for (int i = 1; i < 5; ++i) { + Common::String name = Common::String::format("marb%02u.vga"); + marb[i] = new SpriteResource(name); + } + + if (drawFlag) { + for (int i = 22; i > 0; --i) { + events.updateGameCounter(); + screen.restoreBackground(); + + if (i > 0 && i <= 14) { + hand[i - 1]->draw(screen, 0); + } else { + // TODO: Check '800h'.. horizontal reverse maybe? + hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 14], 0)); + marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 14], 0)); + } + + if (i <= 20) { + marb[i / 5]->draw(screen, i % 5); + } + + while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0) + _vm->_events->pollEventsAndWait(); + + screen._windows[0].update(); + if (i == 0 && doFade) + screen.fadeIn(2); + } + } else { + for (int i = 0; i < 22 && !events.isKeyMousePressed(); ++i) { + events.updateGameCounter(); + screen.restoreBackground(); + + if (i < 14) { + hand[i]->draw(screen, 0); + } + else { + // TODO: Check '800h'.. horizontal reverse maybe? + hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 7], 0)); + marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 7], 0)); + } + + if (i < 20) { + marb[i / 5]->draw(screen, i % 5); + } + + while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0) + _vm->_events->pollEventsAndWait(); + + screen._windows[0].update(); + if (i == 0 && doFade) + screen.fadeIn(2); + } + } + + if (drawFlag) { + hand[0]->draw(screen, 0); + marb[0]->draw(screen, 0); + } else { + screen.restoreBackground(); + } + + screen._windows[0].update(); + restoreButtons(); + + // Free resources + for (int i = 1; i < 5; ++i) + delete marb[i]; + for (int i = 0; i < 16; ++i) + delete hand[i]; +} + +/*------------------------------------------------------------------------*/ + +void DarkSideOptionsMenu::startup(Common::String &title1, Common::String &title2) { + title1 = "title2.int"; + title2 = "title2a.int"; +} + +/** +* Draws the scroll in the background +*/ +void DarkSideOptionsMenu::doScroll(bool drawFlag, bool doFade) { + if (doFade) { + _vm->_screen->fadeIn(2); + } +} + +void WorldOptionsMenu::startup(Common::String &title1, Common::String &title2) { + title1 = "world.int"; + title2 = "start.icn"; + + Screen &screen = *_vm->_screen; + screen.fadeOut(4); + screen.loadPalette("dark.pal"); + screen.fadeIn(0x81); + _vm->_events->clearEvents(); +} + +void WorldOptionsMenu::setBackground() { + Screen &screen = *_vm->_screen; + screen.loadBackground("world.raw"); + screen.saveBackground(); + screen.fadeIn(4); +} + +} // End of namespace Xeen diff --git a/engines/xeen/menus.h b/engines/xeen/menus.h new file mode 100644 index 0000000000..497c193f65 --- /dev/null +++ b/engines/xeen/menus.h @@ -0,0 +1,106 @@ +/* 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 XEEN_MENUS_H +#define XEEN_MENUS_H + +#include "common/array.h" +#include "common/stack.h" +#include "common/rect.h" +#include "xeen/xeen.h" + +namespace Xeen { + +class DialogButton { +public: + Common::Rect _bounds; + int _d; + int _i; +}; + +class Dialog { +private: + Common::Array<DialogButton> _buttons; + Common::Stack< Common::Array<DialogButton> > _savedButtons; +protected: + XeenEngine *_vm; + + virtual void doScroll(bool drawFlag, bool doFade) = 0; +public: + Dialog(XeenEngine *vm): _vm(vm) {} + + void saveButtons(); + + void clearButtons(); + + void restoreButtons(); +}; + +class OptionsMenu: public Dialog { +private: + void execute(); +protected: + OptionsMenu(XeenEngine *vm) : Dialog(vm) {} +protected: + virtual void startup(Common::String &title1, Common::String &title2); + + virtual void setBackground() {} + + virtual void showTitles1(const Common::String &title); + + virtual void showTitles2(); +public: + static void show(XeenEngine *vm); +}; + +class CloudsOptionsMenu : public OptionsMenu { +protected: + virtual void startup(Common::String &title1, Common::String &title2); + + virtual void doScroll(bool drawFlag, bool doFade); +public: + CloudsOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {} +}; + +class DarkSideOptionsMenu : public OptionsMenu { +protected: + virtual void startup(Common::String &title1, Common::String &title2); + + virtual void doScroll(bool drawFlag, bool doFade); +public: + DarkSideOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {} +}; + +class WorldOptionsMenu : public DarkSideOptionsMenu { +protected: + virtual void startup(Common::String &title1, Common::String &title2); + + virtual void setBackground(); + + virtual void showTitles2() {} +public: + WorldOptionsMenu(XeenEngine *vm) : DarkSideOptionsMenu(vm) {} +}; + +} // End of namespace Xeen + +#endif /* XEEN_MENUS_H */ diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index aafe9b4c22..0dd15b90eb 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -7,6 +7,7 @@ MODULE_OBJS := \ debugger.o \ detection.o \ events.o \ + menus.o \ resources.o \ screen.o \ sound.o \ diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index b1275aaf4b..f773ee5d42 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -38,6 +38,11 @@ Window::Window(Screen *screen, const Common::Rect &bounds, int a, int border, _xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) { } +void Window::update() { + // Window updates are not specifically necessary since all drawing + // automatically gets added to the screen's dirty rect list +} + /*------------------------------------------------------------------------*/ /** diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 4178460caa..728140a695 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -53,12 +53,15 @@ public: Window(Screen *screen, const Common::Rect &bounds, int a, int border, int xLo, int ycL, int xHi, int ycH); + + void setBounds(const Common::Rect &r) { _bounds = r; } + + void update(); }; class Screen: public XSurface { private: XeenEngine *_vm; - Common::Array<Window> _windows; Common::List<Common::Rect> _dirtyRects; byte _mainPalette[PALETTE_SIZE]; byte _tempPaltte[PALETTE_SIZE]; @@ -81,6 +84,8 @@ private: void updatePalette(const byte *pal, int start, int count16); public: virtual void addDirtyRect(const Common::Rect &r); +public: + Common::Array<Window> _windows; public: Screen(XeenEngine *vm); @@ -104,9 +109,9 @@ public: void fadeOut(int step); - void saveBackground(int slot); + void saveBackground(int slot = 0); - void restoreBackground(int slot); + void restoreBackground(int slot = 0); }; } // End of namespace Xeen diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index b122fc150f..73f5aa0633 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -38,6 +38,10 @@ public: void proc2(File &f); void startMusic(int v1); + + void playMusic(const File &f) {} + + void playSample(const Common::SeekableReadStream *stream, int v2) {} }; } // End of namespace Xeen diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 5a293636a9..311e139b21 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -214,6 +214,8 @@ void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeade } void XeenEngine::playGame() { + //showIntro(); + } } // End of namespace Xeen -- cgit v1.2.3 From 9506635bad402d58886cc9a47512871b321a10a2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 30 Dec 2014 22:50:24 -1000 Subject: XEEN: Implemented Window functionality --- engines/xeen/events.cpp | 5 ++ engines/xeen/events.h | 5 ++ engines/xeen/menus.cpp | 43 ++++++++++++-- engines/xeen/menus.h | 20 ++++++- engines/xeen/screen.cpp | 147 +++++++++++++++++++++++++++++++++--------------- engines/xeen/screen.h | 21 +++++-- engines/xeen/xeen.cpp | 5 ++ engines/xeen/xeen.h | 8 +++ 8 files changed, 197 insertions(+), 57 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp index 29dde3a031..54cc843dbb 100644 --- a/engines/xeen/events.cpp +++ b/engines/xeen/events.cpp @@ -176,4 +176,9 @@ void EventsManager::nextFrame() { _vm->_screen->update(); } +/*------------------------------------------------------------------------*/ + +GameEvent::GameEvent() { +} + } // End of namespace Xeen diff --git a/engines/xeen/events.h b/engines/xeen/events.h index 3590267b66..bf41bc9f40 100644 --- a/engines/xeen/events.h +++ b/engines/xeen/events.h @@ -79,6 +79,11 @@ public: uint32 timeElapsed(); }; +class GameEvent { +public: + GameEvent(); +}; + } // End of namespace Xeen #endif /* XEEN_EVENTS_H */ diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp index 4ddb85a63d..da272b6f3d 100644 --- a/engines/xeen/menus.cpp +++ b/engines/xeen/menus.cpp @@ -43,6 +43,10 @@ void Dialog::restoreButtons() { _buttons = _savedButtons.pop(); } +void Dialog::addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool d) { + _buttons.push_back(DialogButton(bounds, c, sprites, d)); +} + /*------------------------------------------------------------------------*/ void OptionsMenu::show(XeenEngine *vm) { @@ -77,8 +81,9 @@ void OptionsMenu::execute() { screen._windows[28].setBounds(Common::Rect(72, 25, 248, 175)); - Common::String title1, title2; - startup(title1, title2); + Common::String title1, buttonsName; + startup(title1, buttonsName); + SpriteResource buttonSprites(buttonsName); bool firstTime = true; while (!_vm->shouldQuit()) { @@ -91,10 +96,17 @@ void OptionsMenu::execute() { } for (;;) { - clearButtons(); - showTitles1(title1); showTitles2(); + + reopen: + clearButtons(); + setupButtons(&buttonSprites); + openWindow(); + + while (!_vm->shouldQuit()) { + + } } } } @@ -108,9 +120,9 @@ void OptionsMenu::showTitles1(const Common::String &title) { while (!_vm->shouldQuit() && !events.isKeyMousePressed()) { events.updateGameCounter(); - frame = frame % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10); + frame = ++frame % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10); screen.restoreBackground(); - titleSprites.draw(screen, 0); + titleSprites.draw(screen, frame); while (events.timeElapsed() == 0) events.pollEventsAndWait(); @@ -153,6 +165,20 @@ void OptionsMenu::showTitles2() { screen._windows[0].update(); } +void OptionsMenu::setupButtons(SpriteResource *buttons) { + addButton(Common::Rect(124, 87, 124 + 53, 87 + 10), 'S', buttons, true); + addButton(Common::Rect(126, 98, 126 + 47, 98 + 10), 'L', buttons, true); + addButton(Common::Rect(91, 110, 91 + 118, 110 + 10), 'C', buttons, true); + addButton(Common::Rect(85, 121, 85 + 131, 121 + 10), 'O', buttons, true); +} + +void WorldOptionsMenu::setupButtons(SpriteResource *buttons) { + addButton(Common::Rect(93, 53, 93 + 134, 53 + 20), 'S', buttons, false); + addButton(Common::Rect(93, 78, 93 + 134, 78 + 20), 'L', buttons, false); + addButton(Common::Rect(93, 103, 93 + 134, 103 + 20), 'C', buttons, false); + addButton(Common::Rect(93, 128, 93 + 134, 128 + 20), 'O', buttons, false); +} + /*------------------------------------------------------------------------*/ void CloudsOptionsMenu::startup(Common::String &title1, Common::String &title2) { @@ -289,4 +315,9 @@ void WorldOptionsMenu::setBackground() { screen.fadeIn(4); } +void WorldOptionsMenu::openWindow() { + _vm->_screen->_windows[28].open(); +} + + } // End of namespace Xeen diff --git a/engines/xeen/menus.h b/engines/xeen/menus.h index 497c193f65..774c7cfcb9 100644 --- a/engines/xeen/menus.h +++ b/engines/xeen/menus.h @@ -33,8 +33,14 @@ namespace Xeen { class DialogButton { public: Common::Rect _bounds; - int _d; - int _i; + SpriteResource *_sprites; + char _c; + bool _d; + + DialogButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool d) : + _bounds(bounds), _c(c), _sprites(sprites), _d(d) {} + + DialogButton() : _c('\0'), _sprites(nullptr), _d(false) {} }; class Dialog { @@ -53,6 +59,8 @@ public: void clearButtons(); void restoreButtons(); + + void addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool d); }; class OptionsMenu: public Dialog { @@ -68,6 +76,10 @@ protected: virtual void showTitles1(const Common::String &title); virtual void showTitles2(); + + virtual void setupButtons(SpriteResource *buttons); + + virtual void openWindow() {} public: static void show(XeenEngine *vm); }; @@ -97,6 +109,10 @@ protected: virtual void setBackground(); virtual void showTitles2() {} + + virtual void setupButtons(SpriteResource *buttons); + + virtual void openWindow(); public: WorldOptionsMenu(XeenEngine *vm) : DarkSideOptionsMenu(vm) {} }; diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index f773ee5d42..1f8e50cd87 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -22,25 +22,76 @@ #include "common/system.h" #include "graphics/palette.h" +#include "graphics/surface.h" #include "xeen/screen.h" #include "xeen/resources.h" #include "xeen/xeen.h" namespace Xeen { -Window::Window() : _screen(nullptr), _enabled(false), _a(0), _border(0), +Window::Window() : _vm(nullptr), _enabled(false), _a(0), _border(0), _xLo(0), _xHi(0), _ycL(0), _ycH(0) { } -Window::Window(Screen *screen, const Common::Rect &bounds, int a, int border, +Window::Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border, int xLo, int ycL, int xHi, int ycH): - _screen(screen), _enabled(false), _bounds(bounds), _a(a), _border(border), - _xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) { + _vm(vm), _enabled(false), _a(a), _border(border), + _xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) { + setBounds(bounds); } +void Window::setBounds(const Common::Rect &r) { + _bounds = r; + _innerBounds = r; + _innerBounds.grow(-_border); +} + +void Window::open() { + if (!_enabled) { + _vm->_screen->_windowStack.push_back(this); + open2(); + } + + if (_vm->_mode == MODE_9) { + warning("TODO: copyFileToMemory"); + } +} + +void Window::open2() { + create(_bounds.width(), _bounds.height()); + copyRectToSurface(*_vm->_screen, 0, 0, _bounds); + _dirtyRects.push(_bounds); +} + +void Window::close() { + if (_enabled) { + // Update any remaining pending changes to the screen and free + // the window's internal surface storage + update(); + free(); + + // Remove the window from the stack and flag it as now disabled + for (uint i = 0; i < _vm->_screen->_windowStack.size(); ++i) { + if (_vm->_screen->_windowStack[i] == this) + _vm->_screen->_windowStack.remove_at(i); + } + + _enabled = false; + } + + if (_vm->_mode == MODE_9) { + warning("TODO: copyFileToMemory"); + } +} + +/** + * Pushes any pending changes for the window to the screen + */ void Window::update() { - // Window updates are not specifically necessary since all drawing - // automatically gets added to the screen's dirty rect list + while (!_dirtyRects.empty()) { + Common::Rect r = _dirtyRects.pop(); + blitTo(*_vm->_screen, Common::Point(_bounds.left, _bounds.top)); + } } /*------------------------------------------------------------------------*/ @@ -56,50 +107,56 @@ Screen::Screen(XeenEngine *vm) : _vm(vm) { void Screen::setupWindows() { Window windows[40] = { - Window(this, Common::Rect(0, 0, 320, 200), 0, 0, 0, 0, 320, 200), - Window(this, Common::Rect(237, 9, 317, 74), 0, 0, 237, 12, 307, 68), - Window(this, Common::Rect(225, 1, 319, 73), 1, 8, 225, 1, 319, 73), - Window(this, Common::Rect(0, 0, 230, 149), 0, 0, 9, 8, 216, 140), - Window(this, Common::Rect(235, 148, 309, 189), 2, 8, 0, 0, 0, 0), - Window(this, Common::Rect(70, 20, 250, 183), 3, 8, 80, 38, 240, 166), - Window(this, Common::Rect(52, 149, 268, 197), 4, 8, 0, 0, 0, 0), - Window(this, Common::Rect(108, 0, 200, 200), 5, 0, 0, 0, 0, 0), - Window(this, Common::Rect(232, 9, 312, 74), 0, 0, 0, 0, 0, 0), - Window(this, Common::Rect(103, 156, 217, 186), 6, 8, 0, 0, 0, 0), - Window(this, Common::Rect(226, 0, 319, 146), 7, 8, 0, 0, 0, 0), - Window(this, Common::Rect(8, 8, 224, 140), 8, 8, 8, 8, 224, 200), - Window(this, Common::Rect(0, 143, 320, 199), 9, 8, 0, 0, 0, 0), - Window(this, Common::Rect(50, 103, 266, 139), 10, 8, 0, 0, 0, 0), - Window(this, Common::Rect(0, 7, 320, 138), 11, 8, 0, 0, 0, 0), - Window(this, Common::Rect(50, 71, 182, 129), 12, 8, 0, 0, 0, 0), - Window(this, Common::Rect(228, 106, 319, 146), 13, 8, 0, 0, 0, 0), - Window(this, Common::Rect(20, 142, 290, 199), 14, 8, 0, 0, 0, 0), - Window(this, Common::Rect(0, 20, 320, 180), 15, 8, 0, 0, 0, 0), - Window(this, Common::Rect(231, 48, 317, 141), 16, 8, 0, 0, 0, 0), - Window(this, Common::Rect(72, 37, 248, 163), 17, 8, 0, 0, 0, 0), - Window(this, Common::Rect(99, 59, 237, 141), 18, 8, 99, 59, 237, 0), - Window(this, Common::Rect(65, 23, 250, 163), 19, 8, 75, 36, 245, 141), - Window(this, Common::Rect(80, 28, 256, 148), 20, 8, 80, 28, 256, 172), - Window(this, Common::Rect(0, 0, 320, 146), 21, 8, 0, 0, 320, 148), - Window(this, Common::Rect(27, 6, 207, 142), 22, 8, 0, 0, 0, 146), - Window(this, Common::Rect(15, 15, 161, 91), 23, 8, 0, 0, 0, 0), - Window(this, Common::Rect(90, 45, 220, 157), 24, 8, 0, 0, 0, 0), - Window(this, Common::Rect(0, 0, 320, 200), 25, 8, 0, 0, 0, 0), - Window(this, Common::Rect(0, 101, 320, 146), 26, 8, 0, 101, 320, 0), - Window(this, Common::Rect(0, 0, 320, 108), 27, 8, 0, 0, 0, 45), - Window(this, Common::Rect(50, 112, 266, 148), 28, 8, 0, 0, 0, 0), - Window(this, Common::Rect(12, 11, 164, 94), 0, 0, 0, 0, 52, 0), - Window(this, Common::Rect(8, 147, 224, 192), 0, 8, 0, 0, 0, 94), - Window(this, Common::Rect(232, 74, 312, 138), 29, 8, 0, 0, 0, 0), - Window(this, Common::Rect(226, 26, 319, 146), 30, 8, 0, 0, 0, 0), - Window(this, Common::Rect(225, 74, 319, 154), 31, 8, 0, 0, 0, 0), - Window(this, Common::Rect(27, 6, 195, 142), 0, 8, 0, 0, 0, 0), - Window(this, Common::Rect(225, 140, 319, 199), 0, 8, 0, 0, 0, 0) + Window(_vm, Common::Rect(0, 0, 320, 200), 0, 0, 0, 0, 320, 200), + Window(_vm, Common::Rect(237, 9, 317, 74), 0, 0, 237, 12, 307, 68), + Window(_vm, Common::Rect(225, 1, 319, 73), 1, 8, 225, 1, 319, 73), + Window(_vm, Common::Rect(0, 0, 230, 149), 0, 0, 9, 8, 216, 140), + Window(_vm, Common::Rect(235, 148, 309, 189), 2, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(70, 20, 250, 183), 3, 8, 80, 38, 240, 166), + Window(_vm, Common::Rect(52, 149, 268, 197), 4, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(108, 0, 200, 200), 5, 0, 0, 0, 0, 0), + Window(_vm, Common::Rect(232, 9, 312, 74), 0, 0, 0, 0, 0, 0), + Window(_vm, Common::Rect(103, 156, 217, 186), 6, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(226, 0, 319, 146), 7, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(8, 8, 224, 140), 8, 8, 8, 8, 224, 200), + Window(_vm, Common::Rect(0, 143, 320, 199), 9, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(50, 103, 266, 139), 10, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(0, 7, 320, 138), 11, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(50, 71, 182, 129), 12, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(228, 106, 319, 146), 13, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(20, 142, 290, 199), 14, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(0, 20, 320, 180), 15, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(231, 48, 317, 141), 16, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(72, 37, 248, 163), 17, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(99, 59, 237, 141), 18, 8, 99, 59, 237, 0), + Window(_vm, Common::Rect(65, 23, 250, 163), 19, 8, 75, 36, 245, 141), + Window(_vm, Common::Rect(80, 28, 256, 148), 20, 8, 80, 28, 256, 172), + Window(_vm, Common::Rect(0, 0, 320, 146), 21, 8, 0, 0, 320, 148), + Window(_vm, Common::Rect(27, 6, 207, 142), 22, 8, 0, 0, 0, 146), + Window(_vm, Common::Rect(15, 15, 161, 91), 23, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(90, 45, 220, 157), 24, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(0, 0, 320, 200), 25, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(0, 101, 320, 146), 26, 8, 0, 101, 320, 0), + Window(_vm, Common::Rect(0, 0, 320, 108), 27, 8, 0, 0, 0, 45), + Window(_vm, Common::Rect(50, 112, 266, 148), 28, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(12, 11, 164, 94), 0, 0, 0, 0, 52, 0), + Window(_vm, Common::Rect(8, 147, 224, 192), 0, 8, 0, 0, 0, 94), + Window(_vm, Common::Rect(232, 74, 312, 138), 29, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(226, 26, 319, 146), 30, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(225, 74, 319, 154), 31, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(27, 6, 195, 142), 0, 8, 0, 0, 0, 0), + Window(_vm, Common::Rect(225, 140, 319, 199), 0, 8, 0, 0, 0, 0) }; _windows = Common::Array<Window>(windows, 40); } +void Screen::closeWindows() { + for (int i = (int)_windowStack.size() - 1; i >= 0; --i) + _windowStack[i]->close(); + assert(_windowStack.size() == 0); +} + void Screen::update() { // Merge the dirty rects mergeDirtyRects(); diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 728140a695..b132e3321a 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/system.h" #include "common/array.h" +#include "common/queue.h" #include "common/rect.h" #include "xeen/xsurface.h" @@ -39,22 +40,30 @@ namespace Xeen { class XeenEngine; class Screen; -class Window { +class Window: public XSurface { private: - Screen *_screen; + XeenEngine *_vm; Common::Rect _bounds; + Common::Rect _innerBounds; int _a; int _border; int _xLo, _xHi; int _ycL, _ycH; bool _enabled; + Common::Queue<Common::Rect> _dirtyRects; + + void open2(); public: Window(); - Window(Screen *screen, const Common::Rect &bounds, int a, int border, + Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border, int xLo, int ycL, int xHi, int ycH); - void setBounds(const Common::Rect &r) { _bounds = r; } + void setBounds(const Common::Rect &r); + + void open(); + + void close(); void update(); }; @@ -86,9 +95,13 @@ public: virtual void addDirtyRect(const Common::Rect &r); public: Common::Array<Window> _windows; + + Common::Array<Window *> _windowStack; public: Screen(XeenEngine *vm); + void closeWindows(); + void update(); void loadPalette(const Common::String &name); diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 311e139b21..505d9bd2db 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -38,6 +38,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _events = nullptr; _screen = nullptr; _sound = nullptr; + _eventData = nullptr; } XeenEngine::~XeenEngine() { @@ -45,6 +46,7 @@ XeenEngine::~XeenEngine() { delete _events; delete _screen; delete _sound; + delete _eventData; } void XeenEngine::initialize() { @@ -61,6 +63,9 @@ void XeenEngine::initialize() { _screen = new Screen(this); _sound = new SoundManager(this); + File f("029.obj"); + _eventData = f.readStream(f.size()); + // Set graphics mode initGraphics(320, 200, false); diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index df53b784fc..1b99a85a4b 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -64,6 +64,11 @@ enum XeenDebugChannels { kDebugSound = 1 << 3 }; +enum Mode { + MODE_0 = 0, + MODE_9 = 9 +}; + struct XeenGameDescription; #define XEEN_SAVEGAME_VERSION 1 @@ -110,6 +115,9 @@ public: EventsManager *_events; Screen *_screen; SoundManager *_sound; + Mode _mode; + GameEvent _gameEvent; + Common::SeekableReadStream *_eventData; public: XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); virtual ~XeenEngine(); -- cgit v1.2.3 From 5c88d2cc42d9b6124f552464b9c02e800f3956df Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 31 Dec 2014 11:12:18 -1000 Subject: XEEN: Implement window framing code and dialog event handling --- engines/xeen/events.cpp | 13 ++++ engines/xeen/events.h | 6 +- engines/xeen/menus.cpp | 80 +++++++++++++++++++++--- engines/xeen/menus.h | 25 ++++++-- engines/xeen/module.mk | 1 + engines/xeen/resdata.cpp | 151 ++++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/resdata.h | 35 +++++++++++ engines/xeen/screen.cpp | 60 ++++++++++++++++++ engines/xeen/screen.h | 4 ++ engines/xeen/xsurface.cpp | 36 +++++++++++ engines/xeen/xsurface.h | 11 ++++ 11 files changed, 405 insertions(+), 17 deletions(-) create mode 100644 engines/xeen/resdata.cpp create mode 100644 engines/xeen/resdata.h (limited to 'engines/xeen') diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp index 54cc843dbb..fd0871edbc 100644 --- a/engines/xeen/events.cpp +++ b/engines/xeen/events.cpp @@ -94,6 +94,9 @@ void EventsManager::pollEvents() { case Common::EVENT_KEYDOWN: _keyCode = event.kbd.keycode; break; + case Common::EVENT_MOUSEMOVE: + _mousePos = event.mouse; + break; case Common::EVENT_LBUTTONDOWN: _leftButton = true; return; @@ -168,6 +171,16 @@ uint32 EventsManager::timeElapsed() { return _frameCounter - _gameCounter; } +bool EventsManager::wait(uint numFrames, bool interruptable) { + while (!_vm->shouldQuit() && timeElapsed() < numFrames) { + pollEventsAndWait(); + if (interruptable && (_leftButton || _rightButton || isKeyPending())) + return true; + } + + return false; +} + /** * Handles moving to the next game frame */ diff --git a/engines/xeen/events.h b/engines/xeen/events.h index bf41bc9f40..6183b75105 100644 --- a/engines/xeen/events.h +++ b/engines/xeen/events.h @@ -41,10 +41,12 @@ private: uint32 _gameCounter; uint32 _priorGameCounterTime; Common::KeyCode _keyCode; - bool _leftButton, _rightButton; FramesResource _sprites; void nextFrame(); +public: + bool _leftButton, _rightButton; + Common::Point _mousePos; public: EventsManager(XeenEngine *vm); @@ -77,6 +79,8 @@ public: void updateGameCounter(); uint32 timeElapsed(); + + bool wait(uint numFrames, bool interruptable = false); }; class GameEvent { diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp index da272b6f3d..0a7b0307c6 100644 --- a/engines/xeen/menus.cpp +++ b/engines/xeen/menus.cpp @@ -47,6 +47,39 @@ void Dialog::addButton(const Common::Rect &bounds, char c, SpriteResource *sprit _buttons.push_back(DialogButton(bounds, c, sprites, d)); } +void Dialog::checkEvents() { + EventsManager &events = *_vm->_events; + events.pollEventsAndWait(); + + if (events._leftButton) { + // Check whether any button is selected + events.debounceMouse(); + Common::Point pt = events._mousePos; + + for (uint i = 0; i < _buttons.size(); ++i) { + if (_buttons[i]._bounds.contains(pt)) { + _key = _buttons[i]._c; + return; + } + } + } else if (events.isKeyPending()) { + Common::KeyState keyState; + events.getKey(keyState); + if (keyState.ascii >= 32 && keyState.ascii <= 127) { + _key = keyState.ascii; + return; + } + } +} + +/*------------------------------------------------------------------------*/ + +void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) { + while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID) { + checkEvents(); + } +} + /*------------------------------------------------------------------------*/ void OptionsMenu::show(XeenEngine *vm) { @@ -81,9 +114,9 @@ void OptionsMenu::execute() { screen._windows[28].setBounds(Common::Rect(72, 25, 248, 175)); - Common::String title1, buttonsName; - startup(title1, buttonsName); - SpriteResource buttonSprites(buttonsName); + Common::String title1, title2; + startup(title1, title2); + SpriteResource title1Sprites(title1), title2Sprites(title2); bool firstTime = true; while (!_vm->shouldQuit()) { @@ -96,33 +129,33 @@ void OptionsMenu::execute() { } for (;;) { - showTitles1(title1); + showTitles1(title1Sprites); showTitles2(); reopen: clearButtons(); - setupButtons(&buttonSprites); + setupButtons(&title2Sprites); openWindow(); while (!_vm->shouldQuit()) { + showContents(title1Sprites, true); } } } } -void OptionsMenu::showTitles1(const Common::String &title) { - SpriteResource titleSprites(title); +void OptionsMenu::showTitles1(SpriteResource &sprites) { Screen &screen = *_vm->_screen; EventsManager &events = *_vm->_events; - int frame = 0; + int frameNum = 0; while (!_vm->shouldQuit() && !events.isKeyMousePressed()) { events.updateGameCounter(); - frame = ++frame % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10); + frameNum = ++frameNum % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10); screen.restoreBackground(); - titleSprites.draw(screen, frame); + sprites.draw(screen, frameNum); while (events.timeElapsed() == 0) events.pollEventsAndWait(); @@ -319,5 +352,32 @@ void WorldOptionsMenu::openWindow() { _vm->_screen->_windows[28].open(); } +void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + + events.updateGameCounter(); + _bgFrame = ++_bgFrame % 5; + title1.draw(screen._windows[0], 0); + screen._windows[28].frame(); + + screen._windows[28].writeString("\r\x01\x03c\fdMight and Magic Options\n" + "World of Xeen\x02\n" + "117Copyright (c) 1993 NWC, Inc.\n" + "All Rights Reserved\x01"); + + for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) { + DialogButton &btn = _buttons[btnIndex]; + if (btn._d) { + btn._sprites->draw(screen._windows[0], btnIndex * 2, + Common::Point(btn._bounds.left, btn._bounds.top)); + } + } + + if (waitFlag) { + screen._windows[0].update(); + SettingsBaseDialog::showContents(title1, true); + } +} } // End of namespace Xeen diff --git a/engines/xeen/menus.h b/engines/xeen/menus.h index 774c7cfcb9..07a7bb7e8d 100644 --- a/engines/xeen/menus.h +++ b/engines/xeen/menus.h @@ -45,14 +45,17 @@ public: class Dialog { private: - Common::Array<DialogButton> _buttons; Common::Stack< Common::Array<DialogButton> > _savedButtons; protected: XeenEngine *_vm; + Common::Array<DialogButton> _buttons; + char _key; virtual void doScroll(bool drawFlag, bool doFade) = 0; + + void checkEvents(); public: - Dialog(XeenEngine *vm): _vm(vm) {} + Dialog(XeenEngine *vm): _vm(vm), _key('\0') {} void saveButtons(); @@ -63,17 +66,23 @@ public: void addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool d); }; -class OptionsMenu: public Dialog { +class SettingsBaseDialog : public Dialog { +protected: + virtual void showContents(SpriteResource &title1, bool mode); +public: + SettingsBaseDialog(XeenEngine *vm) : Dialog(vm) {} +}; +class OptionsMenu : public SettingsBaseDialog { private: void execute(); protected: - OptionsMenu(XeenEngine *vm) : Dialog(vm) {} + OptionsMenu(XeenEngine *vm) : SettingsBaseDialog(vm) {} protected: virtual void startup(Common::String &title1, Common::String &title2); virtual void setBackground() {} - virtual void showTitles1(const Common::String &title); + virtual void showTitles1(SpriteResource &sprites); virtual void showTitles2(); @@ -103,6 +112,8 @@ public: }; class WorldOptionsMenu : public DarkSideOptionsMenu { +private: + int _bgFrame; protected: virtual void startup(Common::String &title1, Common::String &title2); @@ -113,8 +124,10 @@ protected: virtual void setupButtons(SpriteResource *buttons); virtual void openWindow(); + + virtual void showContents(SpriteResource &title1, bool mode); public: - WorldOptionsMenu(XeenEngine *vm) : DarkSideOptionsMenu(vm) {} + WorldOptionsMenu(XeenEngine *vm) : DarkSideOptionsMenu(vm), _bgFrame(0) {} }; } // End of namespace Xeen diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 0dd15b90eb..a410fbcf10 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -8,6 +8,7 @@ MODULE_OBJS := \ detection.o \ events.o \ menus.o \ + resdata.o \ resources.o \ screen.o \ sound.o \ diff --git a/engines/xeen/resdata.cpp b/engines/xeen/resdata.cpp new file mode 100644 index 0000000000..44002c62f2 --- /dev/null +++ b/engines/xeen/resdata.cpp @@ -0,0 +1,151 @@ +/* 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/scummsys.h" +#include "xeen/resdata.h" + +namespace Xeen { + +const byte SYMBOLS[20][64] = { + { // 0 + 0x00, 0x00, 0xA8, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x00, 0xA8, 0x9E, 0x9C, 0x9C, 0x9E, 0x9E, 0x9E, + 0xAC, 0x9C, 0xA4, 0xAC, 0xAC, 0x9A, 0x9A, 0x9A, 0xAC, 0x9E, 0xAC, 0xA8, 0xA8, 0xA6, 0x97, 0x98, + 0xAC, 0xA0, 0xAC, 0xAC, 0xA4, 0xA6, 0x98, 0x99, 0x00, 0xAC, 0xA0, 0xA0, 0xA8, 0xAC, 0x9A, 0x9A, + 0x00, 0x00, 0xAC, 0xAC, 0xAC, 0xA4, 0x9B, 0x9A, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xA0, 0x9B, 0x9B, + }, + { // 1 + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, + 0x99, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x99, 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x99, 0x98, 0x98, 0x99, 0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, + 0x9A, 0x9B, 0x9B, 0x9C, 0x9B, 0x9A, 0x9C, 0x9A, 0x9B, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x9A, 0x9B, + }, + { // 2 + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, + 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x99, 0x98, 0x98, 0x99, 0x98, 0x98, 0x97, 0x98, 0x98, + 0x99, 0x98, 0x98, 0x98, 0x99, 0x99, 0x98, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, + 0x9B, 0x9B, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9B, 0x99, 0x9A, 0x9B, 0x9B, 0x9A, 0x9A, 0x99, 0x9A, + }, + { // 3 + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, + 0x99, 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x98, 0x98, 0x97, 0x97, 0x98, 0x98, 0x98, 0x98, + 0x99, 0x99, 0x98, 0x99, 0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, + 0x9B, 0x9C, 0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0x9C, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x9A, + }, + { // 4 + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, + 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x99, 0x9A, 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, + 0x99, 0x99, 0x98, 0x99, 0x99, 0x98, 0x98, 0x98, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, + 0x9A, 0x9C, 0x9B, 0x9B, 0x9C, 0x9B, 0x9B, 0x9B, 0x9A, 0x99, 0x9B, 0x9B, 0x9A, 0x99, 0x9A, 0x9A, + }, + { // 5 + 0xA4, 0xA4, 0xA8, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x9E, 0x9E, 0xA0, 0xA8, 0xAC, 0x00, 0x00, + 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9E, 0xAC, 0x00, 0x97, 0x97, 0x97, 0x98, 0x9C, 0x9C, 0xA0, 0xAC, + 0x99, 0x98, 0x99, 0x99, 0x99, 0x9B, 0xA0, 0xAC, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9B, 0xA0, 0xAC, + 0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x9A, 0x9A, 0x9B, 0x9B, 0xA4, 0xAC, 0x00, + }, + { // 6 + 0x00, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x00, 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x9B, 0x99, + 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x98, 0x99, 0x99, + 0x00, 0xAC, 0xA0, 0x9C, 0x9C, 0xA0, 0x9C, 0x9A, 0x00, 0x00, 0xAC, 0xA4, 0xA0, 0x99, 0x99, 0x99, + 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, + }, + { // 7 + 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x9C, 0x99, 0x99, + 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x00, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, + 0x00, 0x00, 0xAC, 0xA0, 0x9B, 0xA0, 0x9E, 0x9C, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x9C, 0x99, 0x99, + }, + { // 8 + 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x9B, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, + 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x9C, 0x99, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x9E, 0x9C, 0x99, + }, + { // 9 + 0x00, 0x00, 0xAC, 0xA4, 0xA0, 0x9C, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x9C, 0xA0, 0x9C, 0x9A, + 0xAC, 0xA4, 0x9C, 0x9A, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, + 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, + 0x00, 0xAC, 0xA4, 0x9C, 0x9A, 0x9C, 0x99, 0x99, 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x9A, 0x99, 0x99, + }, + { // 10 + 0x99, 0x99, 0x99, 0x9A, 0xA0, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00, + 0x99, 0x99, 0x9C, 0x9E, 0xA4, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x9C, 0x99, 0x9C, 0xA4, 0xAC, 0x00, + 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00, + 0x99, 0x99, 0x99, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x9A, 0x9B, 0x9E, 0x9C, 0x9C, 0xA4, 0xAC, 0x00, + }, + { // 11 + 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0x9E, 0xAC, + 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, + 0x9C, 0x99, 0x99, 0x99, 0x9C, 0x9C, 0xA4, 0xAC, 0x99, 0x9E, 0x9E, 0x9C, 0x9C, 0xA0, 0xAC, 0x00, + }, + { // 12 + 0x99, 0x99, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x9B, 0x9C, 0x9E, 0x9C, 0x9C, 0xA4, 0xAC, 0x00, + 0x99, 0x99, 0x99, 0x99, 0x99, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, + 0x99, 0x99, 0x99, 0x99, 0x9C, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, + 0x99, 0x99, 0x9C, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, + }, + { // 13 + 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00, + 0x99, 0x9B, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x9A, 0x99, 0x9C, 0xA0, 0xAC, 0x00, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x9A, 0x9C, 0xA4, 0xAC, 0x00, + }, + { // 14 + 0x00, 0x00, 0xAC, 0x9E, 0x9C, 0x9C, 0x9C, 0x9B, 0x00, 0xAC, 0x9C, 0xA0, 0x9E, 0xA4, 0xA4, 0xA4, + 0xAC, 0x9C, 0xA4, 0xAC, 0xAC, 0xAC, 0x9C, 0x9E, 0xAC, 0xA0, 0xAC, 0xA8, 0x9E, 0xA8, 0xAC, 0x99, + 0xAC, 0x9E, 0xAC, 0xA8, 0xAC, 0x9E, 0xA4, 0xAC, 0xAC, 0xA4, 0xA0, 0xAC, 0xAC, 0xA0, 0xA4, 0xAC, + 0x00, 0xAC, 0xA4, 0xA0, 0xA0, 0xA4, 0xAC, 0xA4, 0x00, 0x00, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, + }, + { // 15 + 0x9C, 0x9C, 0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, + 0x9E, 0x9E, 0x9E, 0x9C, 0x9E, 0x9E, 0x9E, 0x9E, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x99, 0x98, + 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x9E, 0x9E, 0xA0, + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, + }, + { // 16 + 0x9B, 0x9B, 0x9B, 0x9B, 0x9C, 0x9B, 0x9C, 0x9C, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, + 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9E, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99, + 0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0xA0, 0xA0, 0xA0, 0x9E, 0xA0, 0x9E, 0x9E, 0xA0, + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, + }, + { // 17 + 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9C, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, + 0x9E, 0x9E, 0x9E, 0x9C, 0x9C, 0x9C, 0x9E, 0x9E, 0x98, 0x98, 0x98, 0x99, 0x9A, 0x9A, 0x99, 0x98, + 0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9C, 0xA0, 0x9E, 0x9E, 0xA0, 0xA0, 0xA0, 0xA0, 0x9E, + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, + }, + { // 18 + 0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, + 0x9E, 0x9E, 0x9E, 0x9E, 0x9C, 0x9C, 0x9C, 0x9E, 0x98, 0x98, 0x98, 0x98, 0x9A, 0x9A, 0x98, 0x99, + 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9B, 0x9C, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0xA0, 0xA0, 0xA0, + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, + }, + { // 19 + 0x9C, 0x9B, 0x9C, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0x00, 0x00, + 0x9E, 0x9E, 0x9C, 0x9C, 0x9E, 0xA0, 0xAC, 0x00, 0x99, 0x98, 0x98, 0x99, 0x9A, 0x9A, 0xA0, 0xAC, + 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0xA0, 0xAC, 0xA0, 0xA0, 0x9E, 0xA0, 0xA0, 0xA0, 0xA0, 0xAC, + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0x00, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0x00, 0x00, + } +}; + +} // End of namespace Xeen diff --git a/engines/xeen/resdata.h b/engines/xeen/resdata.h new file mode 100644 index 0000000000..ce355e71cb --- /dev/null +++ b/engines/xeen/resdata.h @@ -0,0 +1,35 @@ +/* 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 XEEN_RESDATA_H +#define XEEN_RESDATA_H + +#include "common/scummsys.h" +#include "gui/debugger.h" + +namespace Xeen { + +extern const byte SYMBOLS[20][64]; + +} // End of namespace Xeen + +#endif /* XEEN_RESDATA_H */ diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 1f8e50cd87..4563e37498 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -61,6 +61,62 @@ void Window::open2() { create(_bounds.width(), _bounds.height()); copyRectToSurface(*_vm->_screen, 0, 0, _bounds); _dirtyRects.push(_bounds); + frame(); +} + +void Window::frame() { + Screen &screen = *_vm->_screen; + int xCount = (_bounds.width() - 9) / SYMBOL_WIDTH; + int yCount = (_bounds.height() - 9) / SYMBOL_HEIGHT; + + // Write the top line + screen._writePos = Common::Point(_bounds.left, _bounds.top); + screen.writeSymbol(0); + + if (xCount > 0) { + int symbolId = 1; + for (int i = 0; i < xCount; ++i) { + screen.writeSymbol(symbolId); + if (++symbolId == 5) + symbolId = 1; + } + } + + screen._writePos.x = _bounds.right - SYMBOL_WIDTH; + screen.writeSymbol(5); + + // Write the vertical edges + if (yCount > 0) { + int symbolId = 6; + for (int i = 0; i < yCount; ++i) { + screen._writePos.y += 8; + + screen._writePos.x = _bounds.left; + screen.writeSymbol(symbolId); + + screen._writePos.x = _bounds.right - SYMBOL_WIDTH; + screen.writeSymbol(symbolId + 4); + + if (++symbolId == 10) + symbolId = 6; + } + } + + // Write the bottom line + screen._writePos = Common::Point(_bounds.left, _bounds.bottom - SYMBOL_HEIGHT); + screen.writeSymbol(14); + + if (xCount > 0) { + int symbolId = 15; + for (int i = 0; i < xCount; ++i) { + screen.writeSymbol(symbolId); + if (++symbolId == 19) + symbolId = 15; + } + } + + screen._writePos.x = _bounds.right - SYMBOL_WIDTH; + screen.writeSymbol(19); } void Window::close() { @@ -94,6 +150,10 @@ void Window::update() { } } +void Window::addDirtyRect(const Common::Rect &r) { + _dirtyRects.push(r); +} + /*------------------------------------------------------------------------*/ /** diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index b132e3321a..cbf57670b3 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -53,6 +53,8 @@ private: Common::Queue<Common::Rect> _dirtyRects; void open2(); +public: + virtual void addDirtyRect(const Common::Rect &r); public: Window(); @@ -66,6 +68,8 @@ public: void close(); void update(); + + void frame(); }; class Screen: public XSurface { diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp index f63ad14350..d3c547861b 100644 --- a/engines/xeen/xsurface.cpp +++ b/engines/xeen/xsurface.cpp @@ -22,6 +22,7 @@ #include "common/algorithm.h" #include "xeen/xsurface.h" +#include "xeen/resdata.h" namespace Xeen { @@ -79,4 +80,39 @@ void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const { dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y)); } +/** + * Draws a symbol to the surface. + * @param symbolId Symbol number from 0 to 19 + */ +void XSurface::writeSymbol(int symbolId) { + const byte *srcP = &SYMBOLS[symbolId][0]; + + for (int yp = 0; yp < SYMBOL_HEIGHT; ++yp) { + byte *destP = (byte *)getBasePtr(_writePos.x, _writePos.y + yp); + + for (int xp = 0; xp < SYMBOL_WIDTH; ++xp, ++destP) { + byte b = *srcP++; + if (b) + *destP = b; + } + } + + _writePos.x += 8; +} + +/** + * Write a string to the surface + */ +void XSurface::writeString(const Common::String &s) { + error("TODO"); +} + +/** + * Wrie a character to the surface + */ +void XSurface::writeChar(char c) { + error("TODO"); +} + + } // End of namespace Xeen diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h index 92f1236349..6688285361 100644 --- a/engines/xeen/xsurface.h +++ b/engines/xeen/xsurface.h @@ -30,7 +30,12 @@ namespace Xeen { +#define SYMBOL_WIDTH 8 +#define SYMBOL_HEIGHT 8 + class XSurface: public Graphics::Surface { +public: + Common::Point _writePos; public: virtual void addDirtyRect(const Common::Rect &r) {} public: @@ -49,6 +54,12 @@ public: void blitTo(XSurface &dest) const; bool empty() const { return getPixels() == nullptr; } + + void writeSymbol(int symbolId); + + void writeString(const Common::String &s); + + void writeChar(char c); }; } // End of namespace Xeen -- cgit v1.2.3 From d21c47e019434797217b1b44708c8f1810a003b3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 31 Dec 2014 16:14:45 -1000 Subject: XEEN: Lot of font code implemented --- engines/xeen/resdata.cpp | 43 ++++++++ engines/xeen/resdata.h | 2 + engines/xeen/screen.cpp | 33 ++++-- engines/xeen/screen.h | 7 +- engines/xeen/xsurface.cpp | 248 ++++++++++++++++++++++++++++++++++++++++++++-- engines/xeen/xsurface.h | 29 +++++- 6 files changed, 345 insertions(+), 17 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/resdata.cpp b/engines/xeen/resdata.cpp index 44002c62f2..1cdd3ac0fb 100644 --- a/engines/xeen/resdata.cpp +++ b/engines/xeen/resdata.cpp @@ -148,4 +148,47 @@ const byte SYMBOLS[20][64] = { } }; +const byte TEXT_COLORS[40][4] = { + { 0x00, 0x19, 0x19, 0x19 }, + { 0x00, 0x08, 0x08, 0x08 }, + { 0x00, 0x0F, 0x0F, 0x0F }, + { 0x00, 0x15, 0x15, 0x15 }, + { 0x00, 0x01, 0x01, 0x01 }, + { 0x00, 0x21, 0x21, 0x21 }, + { 0x00, 0x26, 0x26, 0x26 }, + { 0x00, 0x2B, 0x2B, 0x2B }, + { 0x00, 0x31, 0x31, 0x31 }, + { 0x00, 0x36, 0x36, 0x36 }, + { 0x00, 0x3D, 0x3D, 0x3D }, + { 0x00, 0x41, 0x41, 0x41 }, + { 0x00, 0x46, 0x46, 0x46 }, + { 0x00, 0x4C, 0x4C, 0x4C }, + { 0x00, 0x50, 0x50, 0x50 }, + { 0x00, 0x55, 0x55, 0x55 }, + { 0x00, 0x5D, 0x5D, 0x5D }, + { 0x00, 0x60, 0x60, 0x60 }, + { 0x00, 0x65, 0x65, 0x65 }, + { 0x00, 0x6C, 0x6C, 0x6C }, + { 0x00, 0x70, 0x70, 0x70 }, + { 0x00, 0x75, 0x75, 0x75 }, + { 0x00, 0x7B, 0x7B, 0x7B }, + { 0x00, 0x80, 0x80, 0x80 }, + { 0x00, 0x85, 0x85, 0x85 }, + { 0x00, 0x8D, 0x8D, 0x8D }, + { 0x00, 0x90, 0x90, 0x90 }, + { 0x00, 0x97, 0x97, 0x97 }, + { 0x00, 0x9D, 0x9D, 0x9D }, + { 0x00, 0xA4, 0xA4, 0xA4 }, + { 0x00, 0xAB, 0xAB, 0xAB }, + { 0x00, 0xB0, 0xB0, 0xB0 }, + { 0x00, 0xB6, 0xB6, 0xB6 }, + { 0x00, 0xBD, 0xBD, 0xBD }, + { 0x00, 0xC0, 0xC0, 0xC0 }, + { 0x00, 0xC6, 0xC6, 0xC6 }, + { 0x00, 0xCD, 0xCD, 0xCD }, + { 0x00, 0xD0, 0xD0, 0xD0 }, + { 0x00, 0xD6, 0xD6, 0xD6 }, + { 0x00, 0xDB, 0xDB, 0xDB }, +}; + } // End of namespace Xeen diff --git a/engines/xeen/resdata.h b/engines/xeen/resdata.h index ce355e71cb..deb6e589be 100644 --- a/engines/xeen/resdata.h +++ b/engines/xeen/resdata.h @@ -30,6 +30,8 @@ namespace Xeen { extern const byte SYMBOLS[20][64]; +extern const byte TEXT_COLORS[40][4]; + } // End of namespace Xeen #endif /* XEEN_RESDATA_H */ diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 4563e37498..2da2412866 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -66,8 +66,8 @@ void Window::open2() { void Window::frame() { Screen &screen = *_vm->_screen; - int xCount = (_bounds.width() - 9) / SYMBOL_WIDTH; - int yCount = (_bounds.height() - 9) / SYMBOL_HEIGHT; + int xCount = (_bounds.width() - 9) / FONT_WIDTH; + int yCount = (_bounds.height() - 9) / FONT_HEIGHT; // Write the top line screen._writePos = Common::Point(_bounds.left, _bounds.top); @@ -82,7 +82,7 @@ void Window::frame() { } } - screen._writePos.x = _bounds.right - SYMBOL_WIDTH; + screen._writePos.x = _bounds.right - FONT_WIDTH; screen.writeSymbol(5); // Write the vertical edges @@ -94,7 +94,7 @@ void Window::frame() { screen._writePos.x = _bounds.left; screen.writeSymbol(symbolId); - screen._writePos.x = _bounds.right - SYMBOL_WIDTH; + screen._writePos.x = _bounds.right - FONT_WIDTH; screen.writeSymbol(symbolId + 4); if (++symbolId == 10) @@ -103,7 +103,7 @@ void Window::frame() { } // Write the bottom line - screen._writePos = Common::Point(_bounds.left, _bounds.bottom - SYMBOL_HEIGHT); + screen._writePos = Common::Point(_bounds.left, _bounds.bottom - FONT_HEIGHT); screen.writeSymbol(14); if (xCount > 0) { @@ -115,7 +115,7 @@ void Window::frame() { } } - screen._writePos.x = _bounds.right - SYMBOL_WIDTH; + screen._writePos.x = _bounds.right - FONT_WIDTH; screen.writeSymbol(19); } @@ -154,6 +154,17 @@ void Window::addDirtyRect(const Common::Rect &r) { _dirtyRects.push(r); } +/** + * Fill the content area of a window with the current background color + */ +void Window::fill() { + fillRect(_innerBounds, _bgColor); +} + +void Window::writeString(const Common::String &s) { + _vm->_screen->writeString(s, _innerBounds); +} + /*------------------------------------------------------------------------*/ /** @@ -163,6 +174,16 @@ Screen::Screen(XeenEngine *vm) : _vm(vm) { _fadeIn = false; create(SCREEN_WIDTH, SCREEN_HEIGHT); setupWindows(); + + // Load font data for the screen + File f("fnt"); + byte *data = new byte[f.size()]; + f.read(data, f.size()); + _fontData = data; +} + +Screen::~Screen() { + delete[] _fontData; } void Screen::setupWindows() { diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index cbf57670b3..907409dbfb 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -70,7 +70,10 @@ public: void update(); void frame(); -}; + + void fill(); + + void writeString(const Common::String &s);}; class Screen: public XSurface { private: @@ -104,6 +107,8 @@ public: public: Screen(XeenEngine *vm); + virtual ~Screen(); + void closeWindows(); void update(); diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp index d3c547861b..5e7d831380 100644 --- a/engines/xeen/xsurface.cpp +++ b/engines/xeen/xsurface.cpp @@ -21,16 +21,29 @@ */ #include "common/algorithm.h" +#include "common/util.h" #include "xeen/xsurface.h" #include "xeen/resdata.h" namespace Xeen { -XSurface::XSurface(): Graphics::Surface() { +const byte *XSurface::_fontData; + +XSurface::XSurface() : Graphics::Surface(), _bgColor(DEFAULT_BG_COLOR), _fontReduced(false), + _fontJustify(JUSTIFY_NONE), _msgWraps(false) { + _textColors[0] = 0; + _textColors[1] = 0x40; + _textColors[2] = 0x30; + _textColors[3] = 0x20; } -XSurface::XSurface(int w, int h) : Graphics::Surface() { +XSurface::XSurface(int w, int h) : Graphics::Surface(), _bgColor(DEFAULT_BG_COLOR), + _fontReduced(false), _fontJustify(JUSTIFY_NONE), _msgWraps(false) { create(w, h); + _textColors[0] = 0; + _textColors[1] = 0x40; + _textColors[2] = 0x30; + _textColors[3] = 0x20; } XSurface::~XSurface() { @@ -87,10 +100,10 @@ void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const { void XSurface::writeSymbol(int symbolId) { const byte *srcP = &SYMBOLS[symbolId][0]; - for (int yp = 0; yp < SYMBOL_HEIGHT; ++yp) { + for (int yp = 0; yp < FONT_HEIGHT; ++yp) { byte *destP = (byte *)getBasePtr(_writePos.x, _writePos.y + yp); - for (int xp = 0; xp < SYMBOL_WIDTH; ++xp, ++destP) { + for (int xp = 0; xp < FONT_WIDTH; ++xp, ++destP) { byte b = *srcP++; if (b) *destP = b; @@ -102,9 +115,158 @@ void XSurface::writeSymbol(int symbolId) { /** * Write a string to the surface + * @param s String to display + * @param bounds Window bounds to display string within + * @returns Any string remainder that couldn't be displayed + * @remarks Note that bounds is just used for wrapping purposes. Unless + * justification is set, the message will be written at _writePos */ -void XSurface::writeString(const Common::String &s) { - error("TODO"); +Common::String XSurface::writeString(const Common::String &s, const Common::Rect &bounds) { + _displayString = s.c_str(); + + for (;;) { + _msgWraps = false; + + // Get the size of the string that can be displayed on the likne + int xp = _fontJustify ? bounds.left : _writePos.x; + while (!getNextCharWidth(xp)) { + if (xp >= bounds.right) { + --_displayString; + _msgWraps = true; + } + } + + // Get the end point of the text that can be displayed + const char *displayEnd = _displayString; + _displayString = s.c_str(); + + if (*displayEnd && _fontJustify != JUSTIFY_RIGHT && xp >= bounds.right) { + // Need to handle justification of text + // First, move backwards to find the end of the previous word + // for a convenient point to break the line at + const char *endP = displayEnd; + while (endP > _displayString && (*endP & 0x7f) != ' ') + --endP; + + if (endP == _displayString) { + // There was no word breaks at all in the string + --displayEnd; + if (_fontJustify == JUSTIFY_NONE && _writePos.x != bounds.left) { + // Move to the next line + if (!newLine(bounds)) + continue; + // Ran out of space to display string + break; + } + } else { + // Found word break, find end of previous word + while (displayEnd > _displayString && (*displayEnd & 0x7f) == ' ') + --displayEnd; + } + } + + // Main character display loop + while (_displayString <= displayEnd) { + char c = getNextChar(); + + if (c == ' ') { + _writePos.x += _fontReduced ? 3 : 4; + } else if (c == '\r') { + fillRect(bounds, _bgColor); + _writePos = Common::Point(bounds.left, bounds.top); + } else if (c == 1) { + // Turn off reduced font mode + _fontReduced = false; + } else if (c == 2) { + // Turn on reduced font mode + _fontReduced = true; + } else if (c == 3) { + // Justify text + c = getNextChar(); + if (c == 'r') + _fontJustify = JUSTIFY_RIGHT; + else if (c == 'c') + _fontJustify = JUSTIFY_CENTER; + else + _fontJustify = JUSTIFY_NONE; + } else if (c == 4) { + // Draw an empty box of a given width + int w = fontAtoi(); + Common::Point pt = _writePos; + if (_fontJustify == JUSTIFY_RIGHT) + pt.x -= w; + fillRect(Common::Rect(pt.x, pt.y, pt.x + w, pt.y + (_fontReduced ? 9 : 10)), + _bgColor); + } else if (c == 5) { + continue; + } else if (c == 6) { + // Non-breakable space + writeChar(' '); + } else if (c == 7) { + // Set text background color + int c = fontAtoi(); + _bgColor = (c < 0 || c > 255) ? DEFAULT_BG_COLOR : c; + } else if (c == 8) { + // Draw a character outline + c = getNextChar(); + if (c == ' ') { + c = '\0'; + _writePos.x -= 3; + } else { + if (c == 6) + c = ' '; + byte charSize = _fontData[0x1000 + (int)c + (_fontReduced ? 0x80 : 0)]; + _writePos.x -= charSize; + } + + if (_writePos.x < bounds.left) + _writePos.x = bounds.left; + + if (c) { + int oldX = _writePos.x; + byte oldColor[4]; + Common::copy(&_textColors[0], &_textColors[4], &oldColor[0]); + + _textColors[1] = _textColors[2] = _textColors[3] = _bgColor; + writeChar(c); + + Common::copy(&oldColor[0], &oldColor[4], &_textColors[0]); + _writePos.x = oldX; + } + } else if (c == 9) { + // Skip x position + int xp = fontAtoi(); + _writePos.x = MIN(bounds.left + xp, (int)bounds.right); + } else if (c == 10) { + // Newline + if (newLine(bounds)) + break; + } else if (c == 11) { + // Skip y position + int yp = fontAtoi( ); + _writePos.y = MIN(bounds.top + yp, (int)bounds.bottom); + } else if (c == 12) { + // Set text colors + int idx = fontAtoi(); + if (idx < 0) + idx = 0; + setTextColor(idx); + } else if (c < ' ') { + // Invalid command + displayEnd = nullptr; + break; + } else { + // Standard character - write it out + writeChar(c); + } + } + + if (_displayString > displayEnd && _fontJustify != JUSTIFY_RIGHT && _msgWraps + && newLine(bounds)) + break; + } + + return Common::String(_displayString); } /** @@ -114,5 +276,79 @@ void XSurface::writeChar(char c) { error("TODO"); } +/** + * Return the next pending character to display + */ +char XSurface::getNextChar() { + return *_displayString++ & 0x7f; +} + +/** +* Return the width of a given character +*/ +bool XSurface::getNextCharWidth(int &total) { + char c = getNextChar(); + + if (c > ' ') { + total += _fontData[0x1000 + (int)c + (_fontReduced ? 0x80 : 0)]; + return false; + } else if (c == ' ') { + total += 4; + return false; + } else if (c == 8) { + c = getNextChar(); + if (c == ' ') { + total -= 2; + return false; + } else { + _displayString -= 2; + return true; + } + } else if (c == 12) { + c = getNextChar(); + if (c != 'd') + getNextChar(); + return false; + } else { + --_displayString; + return true; + } +} + +bool XSurface::newLine(const Common::Rect &bounds) { + // Move past any spaces currently being pointed to + while ((*_displayString & 0x7f) == ' ') + ++_displayString; + + _msgWraps = false; + _writePos.x = bounds.left; + + int h = _fontReduced ? 9 : 10; + _writePos.y += h; + + return ((_writePos.y + h - 1) > bounds.bottom); +} + +int XSurface::fontAtoi(int len) { + int total = 0; + for (int i = 0; i < len; ++i) { + char c = getNextChar(); + if (c == ' ') + c = '0'; + + int digit = c - '0'; + if (digit < 0 || digit > 9) + return -1; + + total = total * 10 + digit; + } + + return total; +} + +void XSurface::setTextColor(int idx) { + const byte *colP = &TEXT_COLORS[idx][0]; + Common::copy(colP, colP + 4, &_textColors[0]); +} } // End of namespace Xeen diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h index 6688285361..6e88ae9f97 100644 --- a/engines/xeen/xsurface.h +++ b/engines/xeen/xsurface.h @@ -30,18 +30,39 @@ namespace Xeen { -#define SYMBOL_WIDTH 8 -#define SYMBOL_HEIGHT 8 +#define FONT_WIDTH 8 +#define FONT_HEIGHT 8 +#define DEFAULT_BG_COLOR 0x99 + +enum Justify { JUSTIFY_NONE = 0, JUSTIFY_CENTER = 1, JUSTIFY_RIGHT = 2 }; class XSurface: public Graphics::Surface { +private: + const char *_displayString; + bool _msgWraps; + + char getNextChar(); + + bool getNextCharWidth(int &total); + + bool newLine(const Common::Rect &bounds); + + int fontAtoi(int len = 3); + + void setTextColor(int idx); public: + static const byte *_fontData; Common::Point _writePos; + byte _textColors[4]; + byte _bgColor; + bool _fontReduced; + Justify _fontJustify; public: virtual void addDirtyRect(const Common::Rect &r) {} public: XSurface(); XSurface(int w, int h); - ~XSurface(); + virtual ~XSurface(); void create(uint16 w, uint16 h); @@ -57,7 +78,7 @@ public: void writeSymbol(int symbolId); - void writeString(const Common::String &s); + Common::String writeString(const Common::String &s, const Common::Rect &bounds); void writeChar(char c); }; -- cgit v1.2.3 From c6a2f539d428ea580274a3ac5605e00fad7b8570 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 31 Dec 2014 16:27:37 -1000 Subject: XEEN: Split the font code into it's own file --- engines/xeen/font.cpp | 313 ++++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/font.h | 71 +++++++++++ engines/xeen/module.mk | 1 + engines/xeen/screen.cpp | 2 +- engines/xeen/screen.h | 3 +- engines/xeen/xsurface.cpp | 274 +--------------------------------------- engines/xeen/xsurface.h | 32 ----- 7 files changed, 390 insertions(+), 306 deletions(-) create mode 100644 engines/xeen/font.cpp create mode 100644 engines/xeen/font.h (limited to 'engines/xeen') diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp new file mode 100644 index 0000000000..2894bce7d8 --- /dev/null +++ b/engines/xeen/font.cpp @@ -0,0 +1,313 @@ +/* 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 "xeen/font.h" +#include "xeen/resdata.h" + +namespace Xeen { + +FontSurface::FontSurface() : XSurface(), _fontData(nullptr), _bgColor(DEFAULT_BG_COLOR), + _fontReduced(false),_fontJustify(JUSTIFY_NONE), _msgWraps(false) { + _textColors[0] = 0; + _textColors[1] = 0x40; + _textColors[2] = 0x30; + _textColors[3] = 0x20; +} + +FontSurface::FontSurface(int w, int h) : XSurface(), _fontData(nullptr), _msgWraps(false), + _bgColor(DEFAULT_BG_COLOR), _fontReduced(false), _fontJustify(JUSTIFY_NONE) { + create(w, h); + _textColors[0] = 0; + _textColors[1] = 0x40; + _textColors[2] = 0x30; + _textColors[3] = 0x20; +} + +/** + * Draws a symbol to the surface. + * @param symbolId Symbol number from 0 to 19 + */ +void FontSurface::writeSymbol(int symbolId) { + const byte *srcP = &SYMBOLS[symbolId][0]; + + for (int yp = 0; yp < FONT_HEIGHT; ++yp) { + byte *destP = (byte *)getBasePtr(_writePos.x, _writePos.y + yp); + + for (int xp = 0; xp < FONT_WIDTH; ++xp, ++destP) { + byte b = *srcP++; + if (b) + *destP = b; + } + } + + _writePos.x += 8; +} + +/** + * Write a string to the surface + * @param s String to display + * @param bounds Window bounds to display string within + * @returns Any string remainder that couldn't be displayed + * @remarks Note that bounds is just used for wrapping purposes. Unless + * justification is set, the message will be written at _writePos + */ +Common::String FontSurface::writeString(const Common::String &s, const Common::Rect &bounds) { + _displayString = s.c_str(); + assert(_fontData); + + for (;;) { + _msgWraps = false; + + // Get the size of the string that can be displayed on the likne + int xp = _fontJustify ? bounds.left : _writePos.x; + while (!getNextCharWidth(xp)) { + if (xp >= bounds.right) { + --_displayString; + _msgWraps = true; + } + } + + // Get the end point of the text that can be displayed + const char *displayEnd = _displayString; + _displayString = s.c_str(); + + if (*displayEnd && _fontJustify != JUSTIFY_RIGHT && xp >= bounds.right) { + // Need to handle justification of text + // First, move backwards to find the end of the previous word + // for a convenient point to break the line at + const char *endP = displayEnd; + while (endP > _displayString && (*endP & 0x7f) != ' ') + --endP; + + if (endP == _displayString) { + // There was no word breaks at all in the string + --displayEnd; + if (_fontJustify == JUSTIFY_NONE && _writePos.x != bounds.left) { + // Move to the next line + if (!newLine(bounds)) + continue; + // Ran out of space to display string + break; + } + } else { + // Found word break, find end of previous word + while (displayEnd > _displayString && (*displayEnd & 0x7f) == ' ') + --displayEnd; + } + } + + // Main character display loop + while (_displayString <= displayEnd) { + char c = getNextChar(); + + if (c == ' ') { + _writePos.x += _fontReduced ? 3 : 4; + } else if (c == '\r') { + fillRect(bounds, _bgColor); + _writePos = Common::Point(bounds.left, bounds.top); + } else if (c == 1) { + // Turn off reduced font mode + _fontReduced = false; + } else if (c == 2) { + // Turn on reduced font mode + _fontReduced = true; + } else if (c == 3) { + // Justify text + c = getNextChar(); + if (c == 'r') + _fontJustify = JUSTIFY_RIGHT; + else if (c == 'c') + _fontJustify = JUSTIFY_CENTER; + else + _fontJustify = JUSTIFY_NONE; + } else if (c == 4) { + // Draw an empty box of a given width + int w = fontAtoi(); + Common::Point pt = _writePos; + if (_fontJustify == JUSTIFY_RIGHT) + pt.x -= w; + fillRect(Common::Rect(pt.x, pt.y, pt.x + w, pt.y + (_fontReduced ? 9 : 10)), + _bgColor); + } else if (c == 5) { + continue; + } else if (c == 6) { + // Non-breakable space + writeChar(' '); + } else if (c == 7) { + // Set text background color + int c = fontAtoi(); + _bgColor = (c < 0 || c > 255) ? DEFAULT_BG_COLOR : c; + } else if (c == 8) { + // Draw a character outline + c = getNextChar(); + if (c == ' ') { + c = '\0'; + _writePos.x -= 3; + } else { + if (c == 6) + c = ' '; + byte charSize = _fontData[0x1000 + (int)c + (_fontReduced ? 0x80 : 0)]; + _writePos.x -= charSize; + } + + if (_writePos.x < bounds.left) + _writePos.x = bounds.left; + + if (c) { + int oldX = _writePos.x; + byte oldColor[4]; + Common::copy(&_textColors[0], &_textColors[4], &oldColor[0]); + + _textColors[1] = _textColors[2] = _textColors[3] = _bgColor; + writeChar(c); + + Common::copy(&oldColor[0], &oldColor[4], &_textColors[0]); + _writePos.x = oldX; + } + } else if (c == 9) { + // Skip x position + int xp = fontAtoi(); + _writePos.x = MIN(bounds.left + xp, (int)bounds.right); + } else if (c == 10) { + // Newline + if (newLine(bounds)) + break; + } else if (c == 11) { + // Skip y position + int yp = fontAtoi( ); + _writePos.y = MIN(bounds.top + yp, (int)bounds.bottom); + } else if (c == 12) { + // Set text colors + int idx = fontAtoi(); + if (idx < 0) + idx = 0; + setTextColor(idx); + } else if (c < ' ') { + // Invalid command + displayEnd = nullptr; + break; + } else { + // Standard character - write it out + writeChar(c); + } + } + + if (_displayString > displayEnd && _fontJustify != JUSTIFY_RIGHT && _msgWraps + && newLine(bounds)) + break; + } + + return Common::String(_displayString); +} + +/** + * Return the next pending character to display + */ +char FontSurface::getNextChar() { + return *_displayString++ & 0x7f; +} + +/** +* Return the width of a given character +*/ +bool FontSurface::getNextCharWidth(int &total) { + char c = getNextChar(); + + if (c > ' ') { + total += _fontData[0x1000 + (int)c + (_fontReduced ? 0x80 : 0)]; + return false; + } else if (c == ' ') { + total += 4; + return false; + } else if (c == 8) { + c = getNextChar(); + if (c == ' ') { + total -= 2; + return false; + } else { + _displayString -= 2; + return true; + } + } else if (c == 12) { + c = getNextChar(); + if (c != 'd') + getNextChar(); + return false; + } else { + --_displayString; + return true; + } +} + +/** + * Handles moving to the next line of the given bounded area + */ +bool FontSurface::newLine(const Common::Rect &bounds) { + // Move past any spaces currently being pointed to + while ((*_displayString & 0x7f) == ' ') + ++_displayString; + + _msgWraps = false; + _writePos.x = bounds.left; + + int h = _fontReduced ? 9 : 10; + _writePos.y += h; + + return ((_writePos.y + h - 1) > bounds.bottom); +} + +/** + * Extract a number of a given maximum length from the string + */ +int FontSurface::fontAtoi(int len) { + int total = 0; + for (int i = 0; i < len; ++i) { + char c = getNextChar(); + if (c == ' ') + c = '0'; + + int digit = c - '0'; + if (digit < 0 || digit > 9) + return -1; + + total = total * 10 + digit; + } + + return total; +} + +/** + * Set the text colors based on the specified index in the master text colors list + */ +void FontSurface::setTextColor(int idx) { + const byte *colP = &TEXT_COLORS[idx][0]; + Common::copy(colP, colP + 4, &_textColors[0]); +} + +/** + * Wrie a character to the surface + */ +void FontSurface::writeChar(char c) { + error("TODO"); +} + +} // End of namespace Xeen diff --git a/engines/xeen/font.h b/engines/xeen/font.h new file mode 100644 index 0000000000..0f53d5e6a7 --- /dev/null +++ b/engines/xeen/font.h @@ -0,0 +1,71 @@ +/* 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 XEEN_FONT_H +#define XEEN_FONT_H + +#include "xeen/xsurface.h" + +namespace Xeen { + +#define FONT_WIDTH 8 +#define FONT_HEIGHT 8 +#define DEFAULT_BG_COLOR 0x99 + +enum Justify { JUSTIFY_NONE = 0, JUSTIFY_CENTER = 1, JUSTIFY_RIGHT = 2 }; + +class FontSurface: public XSurface { +private: + const char *_displayString; + bool _msgWraps; + + char getNextChar(); + + bool getNextCharWidth(int &total); + + bool newLine(const Common::Rect &bounds); + + int fontAtoi(int len = 3); + + void setTextColor(int idx); + + void writeChar(char c); +public: + const byte *_fontData; + Common::Point _writePos; + byte _textColors[4]; + byte _bgColor; + bool _fontReduced; + Justify _fontJustify; +public: + FontSurface(); + FontSurface(int w, int h); + virtual ~FontSurface() {} + + void writeSymbol(int symbolId); + + Common::String writeString(const Common::String &s, const Common::Rect &bounds); +}; + +} // End of namespace Xeen + +#endif /* XEEN_FONT_H */ diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index a410fbcf10..9d7b0ebb70 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -7,6 +7,7 @@ MODULE_OBJS := \ debugger.o \ detection.o \ events.o \ + font.o \ menus.o \ resdata.o \ resources.o \ diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 2da2412866..757251ac2a 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -158,7 +158,7 @@ void Window::addDirtyRect(const Common::Rect &r) { * Fill the content area of a window with the current background color */ void Window::fill() { - fillRect(_innerBounds, _bgColor); + fillRect(_innerBounds, _vm->_screen->_bgColor); } void Window::writeString(const Common::String &s) { diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 907409dbfb..4fd19d17eb 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -28,6 +28,7 @@ #include "common/array.h" #include "common/queue.h" #include "common/rect.h" +#include "xeen/font.h" #include "xeen/xsurface.h" namespace Xeen { @@ -75,7 +76,7 @@ public: void writeString(const Common::String &s);}; -class Screen: public XSurface { +class Screen: public FontSurface { private: XeenEngine *_vm; Common::List<Common::Rect> _dirtyRects; diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp index 5e7d831380..cd21a588ef 100644 --- a/engines/xeen/xsurface.cpp +++ b/engines/xeen/xsurface.cpp @@ -27,23 +27,11 @@ namespace Xeen { -const byte *XSurface::_fontData; - -XSurface::XSurface() : Graphics::Surface(), _bgColor(DEFAULT_BG_COLOR), _fontReduced(false), - _fontJustify(JUSTIFY_NONE), _msgWraps(false) { - _textColors[0] = 0; - _textColors[1] = 0x40; - _textColors[2] = 0x30; - _textColors[3] = 0x20; +XSurface::XSurface() : Graphics::Surface() { } -XSurface::XSurface(int w, int h) : Graphics::Surface(), _bgColor(DEFAULT_BG_COLOR), - _fontReduced(false), _fontJustify(JUSTIFY_NONE), _msgWraps(false) { +XSurface::XSurface(int w, int h) : Graphics::Surface() { create(w, h); - _textColors[0] = 0; - _textColors[1] = 0x40; - _textColors[2] = 0x30; - _textColors[3] = 0x20; } XSurface::~XSurface() { @@ -93,262 +81,4 @@ void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const { dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y)); } -/** - * Draws a symbol to the surface. - * @param symbolId Symbol number from 0 to 19 - */ -void XSurface::writeSymbol(int symbolId) { - const byte *srcP = &SYMBOLS[symbolId][0]; - - for (int yp = 0; yp < FONT_HEIGHT; ++yp) { - byte *destP = (byte *)getBasePtr(_writePos.x, _writePos.y + yp); - - for (int xp = 0; xp < FONT_WIDTH; ++xp, ++destP) { - byte b = *srcP++; - if (b) - *destP = b; - } - } - - _writePos.x += 8; -} - -/** - * Write a string to the surface - * @param s String to display - * @param bounds Window bounds to display string within - * @returns Any string remainder that couldn't be displayed - * @remarks Note that bounds is just used for wrapping purposes. Unless - * justification is set, the message will be written at _writePos - */ -Common::String XSurface::writeString(const Common::String &s, const Common::Rect &bounds) { - _displayString = s.c_str(); - - for (;;) { - _msgWraps = false; - - // Get the size of the string that can be displayed on the likne - int xp = _fontJustify ? bounds.left : _writePos.x; - while (!getNextCharWidth(xp)) { - if (xp >= bounds.right) { - --_displayString; - _msgWraps = true; - } - } - - // Get the end point of the text that can be displayed - const char *displayEnd = _displayString; - _displayString = s.c_str(); - - if (*displayEnd && _fontJustify != JUSTIFY_RIGHT && xp >= bounds.right) { - // Need to handle justification of text - // First, move backwards to find the end of the previous word - // for a convenient point to break the line at - const char *endP = displayEnd; - while (endP > _displayString && (*endP & 0x7f) != ' ') - --endP; - - if (endP == _displayString) { - // There was no word breaks at all in the string - --displayEnd; - if (_fontJustify == JUSTIFY_NONE && _writePos.x != bounds.left) { - // Move to the next line - if (!newLine(bounds)) - continue; - // Ran out of space to display string - break; - } - } else { - // Found word break, find end of previous word - while (displayEnd > _displayString && (*displayEnd & 0x7f) == ' ') - --displayEnd; - } - } - - // Main character display loop - while (_displayString <= displayEnd) { - char c = getNextChar(); - - if (c == ' ') { - _writePos.x += _fontReduced ? 3 : 4; - } else if (c == '\r') { - fillRect(bounds, _bgColor); - _writePos = Common::Point(bounds.left, bounds.top); - } else if (c == 1) { - // Turn off reduced font mode - _fontReduced = false; - } else if (c == 2) { - // Turn on reduced font mode - _fontReduced = true; - } else if (c == 3) { - // Justify text - c = getNextChar(); - if (c == 'r') - _fontJustify = JUSTIFY_RIGHT; - else if (c == 'c') - _fontJustify = JUSTIFY_CENTER; - else - _fontJustify = JUSTIFY_NONE; - } else if (c == 4) { - // Draw an empty box of a given width - int w = fontAtoi(); - Common::Point pt = _writePos; - if (_fontJustify == JUSTIFY_RIGHT) - pt.x -= w; - fillRect(Common::Rect(pt.x, pt.y, pt.x + w, pt.y + (_fontReduced ? 9 : 10)), - _bgColor); - } else if (c == 5) { - continue; - } else if (c == 6) { - // Non-breakable space - writeChar(' '); - } else if (c == 7) { - // Set text background color - int c = fontAtoi(); - _bgColor = (c < 0 || c > 255) ? DEFAULT_BG_COLOR : c; - } else if (c == 8) { - // Draw a character outline - c = getNextChar(); - if (c == ' ') { - c = '\0'; - _writePos.x -= 3; - } else { - if (c == 6) - c = ' '; - byte charSize = _fontData[0x1000 + (int)c + (_fontReduced ? 0x80 : 0)]; - _writePos.x -= charSize; - } - - if (_writePos.x < bounds.left) - _writePos.x = bounds.left; - - if (c) { - int oldX = _writePos.x; - byte oldColor[4]; - Common::copy(&_textColors[0], &_textColors[4], &oldColor[0]); - - _textColors[1] = _textColors[2] = _textColors[3] = _bgColor; - writeChar(c); - - Common::copy(&oldColor[0], &oldColor[4], &_textColors[0]); - _writePos.x = oldX; - } - } else if (c == 9) { - // Skip x position - int xp = fontAtoi(); - _writePos.x = MIN(bounds.left + xp, (int)bounds.right); - } else if (c == 10) { - // Newline - if (newLine(bounds)) - break; - } else if (c == 11) { - // Skip y position - int yp = fontAtoi( ); - _writePos.y = MIN(bounds.top + yp, (int)bounds.bottom); - } else if (c == 12) { - // Set text colors - int idx = fontAtoi(); - if (idx < 0) - idx = 0; - setTextColor(idx); - } else if (c < ' ') { - // Invalid command - displayEnd = nullptr; - break; - } else { - // Standard character - write it out - writeChar(c); - } - } - - if (_displayString > displayEnd && _fontJustify != JUSTIFY_RIGHT && _msgWraps - && newLine(bounds)) - break; - } - - return Common::String(_displayString); -} - -/** - * Wrie a character to the surface - */ -void XSurface::writeChar(char c) { - error("TODO"); -} - -/** - * Return the next pending character to display - */ -char XSurface::getNextChar() { - return *_displayString++ & 0x7f; -} - -/** -* Return the width of a given character -*/ -bool XSurface::getNextCharWidth(int &total) { - char c = getNextChar(); - - if (c > ' ') { - total += _fontData[0x1000 + (int)c + (_fontReduced ? 0x80 : 0)]; - return false; - } else if (c == ' ') { - total += 4; - return false; - } else if (c == 8) { - c = getNextChar(); - if (c == ' ') { - total -= 2; - return false; - } else { - _displayString -= 2; - return true; - } - } else if (c == 12) { - c = getNextChar(); - if (c != 'd') - getNextChar(); - return false; - } else { - --_displayString; - return true; - } -} - -bool XSurface::newLine(const Common::Rect &bounds) { - // Move past any spaces currently being pointed to - while ((*_displayString & 0x7f) == ' ') - ++_displayString; - - _msgWraps = false; - _writePos.x = bounds.left; - - int h = _fontReduced ? 9 : 10; - _writePos.y += h; - - return ((_writePos.y + h - 1) > bounds.bottom); -} - -int XSurface::fontAtoi(int len) { - int total = 0; - for (int i = 0; i < len; ++i) { - char c = getNextChar(); - if (c == ' ') - c = '0'; - - int digit = c - '0'; - if (digit < 0 || digit > 9) - return -1; - - total = total * 10 + digit; - } - - return total; -} - -void XSurface::setTextColor(int idx) { - const byte *colP = &TEXT_COLORS[idx][0]; - Common::copy(colP, colP + 4, &_textColors[0]); -} - } // End of namespace Xeen diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h index 6e88ae9f97..64cdab0953 100644 --- a/engines/xeen/xsurface.h +++ b/engines/xeen/xsurface.h @@ -30,33 +30,7 @@ namespace Xeen { -#define FONT_WIDTH 8 -#define FONT_HEIGHT 8 -#define DEFAULT_BG_COLOR 0x99 - -enum Justify { JUSTIFY_NONE = 0, JUSTIFY_CENTER = 1, JUSTIFY_RIGHT = 2 }; - class XSurface: public Graphics::Surface { -private: - const char *_displayString; - bool _msgWraps; - - char getNextChar(); - - bool getNextCharWidth(int &total); - - bool newLine(const Common::Rect &bounds); - - int fontAtoi(int len = 3); - - void setTextColor(int idx); -public: - static const byte *_fontData; - Common::Point _writePos; - byte _textColors[4]; - byte _bgColor; - bool _fontReduced; - Justify _fontJustify; public: virtual void addDirtyRect(const Common::Rect &r) {} public: @@ -75,12 +49,6 @@ public: void blitTo(XSurface &dest) const; bool empty() const { return getPixels() == nullptr; } - - void writeSymbol(int symbolId); - - Common::String writeString(const Common::String &s, const Common::Rect &bounds); - - void writeChar(char c); }; } // End of namespace Xeen -- cgit v1.2.3 From 6e587578c64a7439c330dff09ee1205a97c5b24a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 31 Dec 2014 16:38:17 -1000 Subject: XEEN: Implemented writeChar --- engines/xeen/font.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp index 2894bce7d8..dd1b4dc321 100644 --- a/engines/xeen/font.cpp +++ b/engines/xeen/font.cpp @@ -20,6 +20,7 @@ * */ +#include "common/endian.h" #include "xeen/font.h" #include "xeen/resdata.h" @@ -307,7 +308,29 @@ void FontSurface::setTextColor(int idx) { * Wrie a character to the surface */ void FontSurface::writeChar(char c) { - error("TODO"); + // Get y position, handling kerning + int y = _writePos.y; + if (c == 'g' || c == 'p' || c == 'q' || c == 'y') + ++y; + + // Get pointers into font data and surface to write pixels to + int charIndex = (int)c + (_fontReduced ? 0x80 : 0); + const byte *srcP = &_fontData[charIndex * 16]; + + for (int yp = 0; yp < FONT_HEIGHT; ++yp, ++y) { + uint16 lineData = READ_LE_UINT16(srcP); srcP += 2; + byte *destP = (byte *)getBasePtr(_writePos.x, y); + + for (int xp = 0; xp < FONT_WIDTH; ++xp, ++destP) { + int colIndex = lineData & 3; + lineData >>= 2; + + if (colIndex) + *destP = _textColors[colIndex]; + } + } + + _writePos.x += _fontData[0x1000 + charIndex]; } } // End of namespace Xeen -- cgit v1.2.3 From 9eb229273668b96f63162cabfd769035f95e8a8b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 31 Dec 2014 16:54:14 -1000 Subject: XEEN: Compilation fixes --- engines/xeen/menus.h | 6 ++---- engines/xeen/worldofxeen/worldofxeen_game.cpp | 10 +--------- engines/xeen/xeen.cpp | 4 ++-- 3 files changed, 5 insertions(+), 15 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/menus.h b/engines/xeen/menus.h index 07a7bb7e8d..8cc004ac6f 100644 --- a/engines/xeen/menus.h +++ b/engines/xeen/menus.h @@ -51,7 +51,7 @@ protected: Common::Array<DialogButton> _buttons; char _key; - virtual void doScroll(bool drawFlag, bool doFade) = 0; + virtual void doScroll(bool drawFlag, bool doFade); void checkEvents(); public: @@ -78,7 +78,7 @@ private: protected: OptionsMenu(XeenEngine *vm) : SettingsBaseDialog(vm) {} protected: - virtual void startup(Common::String &title1, Common::String &title2); + virtual void startup(Common::String &title1, Common::String &title2) = 0; virtual void setBackground() {} @@ -96,8 +96,6 @@ public: class CloudsOptionsMenu : public OptionsMenu { protected: virtual void startup(Common::String &title1, Common::String &title2); - - virtual void doScroll(bool drawFlag, bool doFade); public: CloudsOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {} }; diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp index 8057331250..bcfbaa1675 100644 --- a/engines/xeen/worldofxeen/worldofxeen_game.cpp +++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp @@ -30,15 +30,7 @@ WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *g } void WorldOfXeenEngine::playGame () { - _screen->loadPalette("mm4.pal"); - _screen->fadeIn(4); - - //darkSideIntro(); - _events->setCursor(0); - _events->showCursor(); - while (!shouldQuit()) { - _events->pollEventsAndWait(); - } + XeenEngine::playGame(); } } // End of namespace Xeen diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 505d9bd2db..372bbb1b46 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -28,6 +28,7 @@ #include "graphics/scaler.h" #include "graphics/thumbnail.h" #include "xeen/xeen.h" +#include "xeen/menus.h" #include "xeen/resources.h" namespace Xeen { @@ -219,8 +220,7 @@ void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeade } void XeenEngine::playGame() { - //showIntro(); - + OptionsMenu::show(this); } } // End of namespace Xeen -- cgit v1.2.3 From 4a953b06619aae4eded66f868c0f48fb2330d8fa Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 31 Dec 2014 21:09:13 -1000 Subject: XEEN: Startup fixes; options menu buttons now showing --- engines/xeen/events.cpp | 1 + engines/xeen/font.cpp | 10 +++++++--- engines/xeen/menus.cpp | 35 ++++++++++++++++++----------------- engines/xeen/menus.h | 14 +++++++------- engines/xeen/screen.cpp | 16 +++++++++------- engines/xeen/screen.h | 10 +++++----- engines/xeen/xeen.cpp | 1 + engines/xeen/xsurface.cpp | 21 +++++++++++++++++---- engines/xeen/xsurface.h | 4 ++++ 9 files changed, 69 insertions(+), 43 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp index fd0871edbc..285005af98 100644 --- a/engines/xeen/events.cpp +++ b/engines/xeen/events.cpp @@ -55,6 +55,7 @@ void EventsManager::setCursor(int cursorId) { _sprites.draw(cursor, cursorId); CursorMan.replaceCursor(cursor.getPixels(), cursor.w, cursor.h, 0, 0, 0); + showCursor(); } /** diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp index dd1b4dc321..018536b5bf 100644 --- a/engines/xeen/font.cpp +++ b/engines/xeen/font.cpp @@ -124,6 +124,7 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R _writePos.x += _fontReduced ? 3 : 4; } else if (c == '\r') { fillRect(bounds, _bgColor); + addDirtyRect(bounds); _writePos = Common::Point(bounds.left, bounds.top); } else if (c == 1) { // Turn off reduced font mode @@ -146,8 +147,9 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R Common::Point pt = _writePos; if (_fontJustify == JUSTIFY_RIGHT) pt.x -= w; - fillRect(Common::Rect(pt.x, pt.y, pt.x + w, pt.y + (_fontReduced ? 9 : 10)), - _bgColor); + + Common::Rect r(pt.x, pt.y, pt.x + w, pt.y + (_fontReduced ? 9 : 10)); + fillRect(r, _bgColor); } else if (c == 5) { continue; } else if (c == 6) { @@ -194,7 +196,7 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R break; } else if (c == 11) { // Skip y position - int yp = fontAtoi( ); + int yp = fontAtoi(); _writePos.y = MIN(bounds.top + yp, (int)bounds.bottom); } else if (c == 12) { // Set text colors @@ -330,6 +332,8 @@ void FontSurface::writeChar(char c) { } } + addDirtyRect(Common::Rect(_writePos.x, _writePos.y, _writePos.x + FONT_WIDTH, + _writePos.y + FONT_HEIGHT)); _writePos.x += _fontData[0x1000 + charIndex]; } diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp index 0a7b0307c6..4e2226819a 100644 --- a/engines/xeen/menus.cpp +++ b/engines/xeen/menus.cpp @@ -43,8 +43,8 @@ void Dialog::restoreButtons() { _buttons = _savedButtons.pop(); } -void Dialog::addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool d) { - _buttons.push_back(DialogButton(bounds, c, sprites, d)); +void Dialog::addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw = true) { + _buttons.push_back(DialogButton(bounds, c, sprites, draw)); } void Dialog::checkEvents() { @@ -118,9 +118,9 @@ void OptionsMenu::execute() { startup(title1, title2); SpriteResource title1Sprites(title1), title2Sprites(title2); - bool firstTime = true; + bool firstTime = true, doFade = true; while (!_vm->shouldQuit()) { - setBackground(); + setBackground(doFade); events.setCursor(0); if (firstTime) { @@ -128,7 +128,7 @@ void OptionsMenu::execute() { warning("TODO: Read existing save file"); } - for (;;) { + while (!_vm->shouldQuit()) { showTitles1(title1Sprites); showTitles2(); @@ -199,17 +199,17 @@ void OptionsMenu::showTitles2() { } void OptionsMenu::setupButtons(SpriteResource *buttons) { - addButton(Common::Rect(124, 87, 124 + 53, 87 + 10), 'S', buttons, true); - addButton(Common::Rect(126, 98, 126 + 47, 98 + 10), 'L', buttons, true); - addButton(Common::Rect(91, 110, 91 + 118, 110 + 10), 'C', buttons, true); - addButton(Common::Rect(85, 121, 85 + 131, 121 + 10), 'O', buttons, true); + addButton(Common::Rect(124, 87, 124 + 53, 87 + 10), 'S', buttons, false); + addButton(Common::Rect(126, 98, 126 + 47, 98 + 10), 'L', buttons, false); + addButton(Common::Rect(91, 110, 91 + 118, 110 + 10), 'C', buttons, false); + addButton(Common::Rect(85, 121, 85 + 131, 121 + 10), 'O', buttons, false); } void WorldOptionsMenu::setupButtons(SpriteResource *buttons) { - addButton(Common::Rect(93, 53, 93 + 134, 53 + 20), 'S', buttons, false); - addButton(Common::Rect(93, 78, 93 + 134, 78 + 20), 'L', buttons, false); - addButton(Common::Rect(93, 103, 93 + 134, 103 + 20), 'C', buttons, false); - addButton(Common::Rect(93, 128, 93 + 134, 128 + 20), 'O', buttons, false); + addButton(Common::Rect(93, 53, 93 + 134, 53 + 20), 'S', buttons, true); + addButton(Common::Rect(93, 78, 93 + 134, 78 + 20), 'L', buttons, true); + addButton(Common::Rect(93, 103, 93 + 134, 103 + 20), 'C', buttons, true); + addButton(Common::Rect(93, 128, 93 + 134, 128 + 20), 'O', buttons, true); } /*------------------------------------------------------------------------*/ @@ -337,15 +337,16 @@ void WorldOptionsMenu::startup(Common::String &title1, Common::String &title2) { Screen &screen = *_vm->_screen; screen.fadeOut(4); screen.loadPalette("dark.pal"); - screen.fadeIn(0x81); _vm->_events->clearEvents(); } -void WorldOptionsMenu::setBackground() { +void WorldOptionsMenu::setBackground(bool doFade) { Screen &screen = *_vm->_screen; screen.loadBackground("world.raw"); screen.saveBackground(); - screen.fadeIn(4); + + if (doFade) + screen.fadeIn(4); } void WorldOptionsMenu::openWindow() { @@ -368,7 +369,7 @@ void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) { for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) { DialogButton &btn = _buttons[btnIndex]; - if (btn._d) { + if (btn._draw) { btn._sprites->draw(screen._windows[0], btnIndex * 2, Common::Point(btn._bounds.left, btn._bounds.top)); } diff --git a/engines/xeen/menus.h b/engines/xeen/menus.h index 8cc004ac6f..65e3553110 100644 --- a/engines/xeen/menus.h +++ b/engines/xeen/menus.h @@ -35,12 +35,12 @@ public: Common::Rect _bounds; SpriteResource *_sprites; char _c; - bool _d; + bool _draw; - DialogButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool d) : - _bounds(bounds), _c(c), _sprites(sprites), _d(d) {} + DialogButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw) : + _bounds(bounds), _c(c), _sprites(sprites), _draw(draw) {} - DialogButton() : _c('\0'), _sprites(nullptr), _d(false) {} + DialogButton() : _c('\0'), _sprites(nullptr), _draw(false) {} }; class Dialog { @@ -63,7 +63,7 @@ public: void restoreButtons(); - void addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool d); + void addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw); }; class SettingsBaseDialog : public Dialog { @@ -80,7 +80,7 @@ protected: protected: virtual void startup(Common::String &title1, Common::String &title2) = 0; - virtual void setBackground() {} + virtual void setBackground(bool doFade) {} virtual void showTitles1(SpriteResource &sprites); @@ -115,7 +115,7 @@ private: protected: virtual void startup(Common::String &title1, Common::String &title2); - virtual void setBackground(); + virtual void setBackground(bool doFade); virtual void showTitles2() {} diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 757251ac2a..7b1dd1b724 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -29,7 +29,7 @@ namespace Xeen { -Window::Window() : _vm(nullptr), _enabled(false), _a(0), _border(0), +Window::Window() : _vm(nullptr), _enabled(false), _a(0), _border(0), _xLo(0), _xHi(0), _ycL(0), _ycH(0) { } @@ -38,6 +38,7 @@ Window::Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border, _vm(vm), _enabled(false), _a(a), _border(border), _xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) { setBounds(bounds); + create(_vm->_screen, Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); } void Window::setBounds(const Common::Rect &r) { @@ -48,6 +49,7 @@ void Window::setBounds(const Common::Rect &r) { void Window::open() { if (!_enabled) { + _enabled = true; _vm->_screen->_windowStack.push_back(this); open2(); } @@ -58,10 +60,9 @@ void Window::open() { } void Window::open2() { - create(_bounds.width(), _bounds.height()); - copyRectToSurface(*_vm->_screen, 0, 0, _bounds); _dirtyRects.push(_bounds); frame(); + fill(); } void Window::frame() { @@ -173,7 +174,8 @@ void Window::writeString(const Common::String &s) { Screen::Screen(XeenEngine *vm) : _vm(vm) { _fadeIn = false; create(SCREEN_WIDTH, SCREEN_HEIGHT); - setupWindows(); + Common::fill(&_tempPalette[0], &_tempPalette[PALETTE_SIZE], 0); + Common::fill(&_mainPalette[0], &_mainPalette[PALETTE_SIZE], 0); // Load font data for the screen File f("fnt"); @@ -257,6 +259,7 @@ void Screen::update() { } void Screen::addDirtyRect(const Common::Rect &r) { + assert(r.isValidRect() && r.width() > 0 && r.height() > 0); _dirtyRects.push_back(r); } @@ -304,7 +307,7 @@ bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, co void Screen::loadPalette(const Common::String &name) { File f(name); for (int i = 0; i < PALETTE_SIZE; ++i) - _tempPaltte[i] = f.readByte() << 2; + _tempPalette[i] = f.readByte() << 2; } /** @@ -411,7 +414,7 @@ void Screen::fadeInner(int step) { } else { // Create a scaled palette from the temporary one for (int i = 0; i < PALETTE_SIZE; ++i) { - _mainPalette[i] = (_tempPaltte[i] * val * 2) >> 8; + _mainPalette[i] = (_tempPalette[i] * val * 2) >> 8; } updatePalette(); @@ -438,7 +441,6 @@ void Screen::restoreBackground(int slot) { assert(slot > 0 && slot < 10); _savedScreens[slot - 1].blitTo(*this); - _savedScreens[slot - 1].free(); } diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 4fd19d17eb..41b2821c29 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -81,13 +81,11 @@ private: XeenEngine *_vm; Common::List<Common::Rect> _dirtyRects; byte _mainPalette[PALETTE_SIZE]; - byte _tempPaltte[PALETTE_SIZE]; + byte _tempPalette[PALETTE_SIZE]; XSurface _pages[2]; XSurface _savedScreens[10]; bool _fadeIn; - void setupWindows(); - void mergeDirtyRects(); bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2); @@ -110,6 +108,8 @@ public: virtual ~Screen(); + void setupWindows(); + void closeWindows(); void update(); @@ -132,9 +132,9 @@ public: void fadeOut(int step); - void saveBackground(int slot = 0); + void saveBackground(int slot = 1); - void restoreBackground(int slot = 0); + void restoreBackground(int slot = 1); }; } // End of namespace Xeen diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 372bbb1b46..1027572c67 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -62,6 +62,7 @@ void XeenEngine::initialize() { _debugger = new Debugger(this); _events = new EventsManager(this); _screen = new Screen(this); + _screen->setupWindows(); _sound = new SoundManager(this); File f("029.obj"); diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp index cd21a588ef..dc42a6fb24 100644 --- a/engines/xeen/xsurface.cpp +++ b/engines/xeen/xsurface.cpp @@ -27,21 +27,34 @@ namespace Xeen { -XSurface::XSurface() : Graphics::Surface() { +XSurface::XSurface() : Graphics::Surface(), _freeFlag(false) { } -XSurface::XSurface(int w, int h) : Graphics::Surface() { +XSurface::XSurface(int w, int h) : Graphics::Surface(), _freeFlag(false) { create(w, h); } XSurface::~XSurface() { - free(); + if (_freeFlag) + free(); } void XSurface::create(uint16 w, uint16 h) { Graphics::Surface::create(w, h, Graphics::PixelFormat::createFormatCLUT8()); + _freeFlag = true; } +void XSurface::create(XSurface *s, const Common::Rect &bounds) { + pixels = (byte *)s->getBasePtr(bounds.left, bounds.top); + format = Graphics::PixelFormat::createFormatCLUT8(); + pitch = s->pitch; + w = bounds.width(); + h = bounds.height(); + + _freeFlag = false; +} + + void XSurface::transBlitTo(XSurface &dest) const { transBlitTo(dest, Common::Point()); } @@ -78,7 +91,7 @@ void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const { Common::copy(srcP, srcP + w, destP); } - dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y)); + dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y + h)); } } // End of namespace Xeen diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h index 64cdab0953..263ea5336f 100644 --- a/engines/xeen/xsurface.h +++ b/engines/xeen/xsurface.h @@ -31,6 +31,8 @@ namespace Xeen { class XSurface: public Graphics::Surface { +private: + bool _freeFlag; public: virtual void addDirtyRect(const Common::Rect &r) {} public: @@ -40,6 +42,8 @@ public: void create(uint16 w, uint16 h); + void create(XSurface *s, const Common::Rect &bounds); + void transBlitTo(XSurface &dest) const; void transBlitTo(XSurface &dest, const Common::Point &destPos) const; -- cgit v1.2.3 From fb6e8054f7d669e6f2812b07e8d9bc7412c242f7 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 31 Dec 2014 22:55:10 -1000 Subject: XEEN: Fixes for text display --- engines/xeen/font.cpp | 50 ++++++++++++++++++++++++++++++++++++++++--------- engines/xeen/menus.cpp | 4 ++-- engines/xeen/screen.cpp | 3 ++- 3 files changed, 45 insertions(+), 12 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp index 018536b5bf..8b80ec24ca 100644 --- a/engines/xeen/font.cpp +++ b/engines/xeen/font.cpp @@ -76,22 +76,24 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R assert(_fontData); for (;;) { + const char *msgStartP = _displayString; _msgWraps = false; - // Get the size of the string that can be displayed on the likne - int xp = _fontJustify ? bounds.left : _writePos.x; + // Get the size of the string that can be displayed on the line + int xp = _fontJustify == JUSTIFY_CENTER ? bounds.left : _writePos.x; while (!getNextCharWidth(xp)) { if (xp >= bounds.right) { --_displayString; _msgWraps = true; + break; } } // Get the end point of the text that can be displayed const char *displayEnd = _displayString; - _displayString = s.c_str(); + _displayString = msgStartP; - if (*displayEnd && _fontJustify != JUSTIFY_RIGHT && xp >= bounds.right) { + if (_msgWraps && _fontJustify != JUSTIFY_RIGHT && xp >= bounds.right) { // Need to handle justification of text // First, move backwards to find the end of the previous word // for a convenient point to break the line at @@ -116,6 +118,34 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R } } + // Justification adjustment + if (_fontJustify != JUSTIFY_NONE) { + // Figure out the width of the selected portion of the string + int totalWidth = 0; + while (!getNextCharWidth(totalWidth)) { + if (_displayString > displayEnd && *displayEnd == ' ') { + // Don't include any ending space as part of the total + totalWidth -= _fontReduced ? 4 : 5; + } + } + + // Reset starting position back to the start of the string portion + _displayString = msgStartP; + + if (_fontJustify == JUSTIFY_RIGHT) { + // Right aligned + if (_writePos.x == bounds.left) + _writePos.x = bounds.right; + _writePos.x -= totalWidth + 1; + } else { + // Center aligned + if (_writePos.x == bounds.left) + _writePos.x = (bounds.left + bounds.right + 1 - totalWidth) / 2; + else + _writePos.x = (_writePos.x * 2 - totalWidth) / 2; + } + } + // Main character display loop while (_displayString <= displayEnd) { char c = getNextChar(); @@ -195,18 +225,18 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R if (newLine(bounds)) break; } else if (c == 11) { - // Skip y position + // Set y position int yp = fontAtoi(); _writePos.y = MIN(bounds.top + yp, (int)bounds.bottom); } else if (c == 12) { // Set text colors - int idx = fontAtoi(); + int idx = fontAtoi(2); if (idx < 0) idx = 0; setTextColor(idx); } else if (c < ' ') { - // Invalid command - displayEnd = nullptr; + // End of string or invalid command + _displayString = nullptr; break; } else { // Standard character - write it out @@ -214,7 +244,9 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R } } - if (_displayString > displayEnd && _fontJustify != JUSTIFY_RIGHT && _msgWraps + if (!_displayString) + break; + if ( _displayString > displayEnd && _fontJustify != JUSTIFY_RIGHT && _msgWraps && newLine(bounds)) break; } diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp index 4e2226819a..ea2904a5e4 100644 --- a/engines/xeen/menus.cpp +++ b/engines/xeen/menus.cpp @@ -362,9 +362,9 @@ void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) { title1.draw(screen._windows[0], 0); screen._windows[28].frame(); - screen._windows[28].writeString("\r\x01\x03c\fdMight and Magic Options\n" + screen._windows[28].writeString("\x0D\x01\003c\014dMight and Magic Options\n" "World of Xeen\x02\n" - "117Copyright (c) 1993 NWC, Inc.\n" + "\v117Copyright (c) 1993 NWC, Inc.\n" "All Rights Reserved\x01"); for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) { diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 7b1dd1b724..6d5caae35f 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -259,7 +259,8 @@ void Screen::update() { } void Screen::addDirtyRect(const Common::Rect &r) { - assert(r.isValidRect() && r.width() > 0 && r.height() > 0); + assert(r.isValidRect() && r.width() > 0 && r.height() > 0 + && r.right <= SCREEN_WIDTH && r.bottom <= SCREEN_HEIGHT); _dirtyRects.push_back(r); } -- cgit v1.2.3 From 4dd8c68df227654329601dc06ba5eccdcafa45f0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 31 Dec 2014 23:13:49 -1000 Subject: XEEN: Fix background animation for Options menu --- engines/xeen/menus.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp index ea2904a5e4..68ef87a853 100644 --- a/engines/xeen/menus.cpp +++ b/engines/xeen/menus.cpp @@ -75,9 +75,7 @@ void Dialog::checkEvents() { /*------------------------------------------------------------------------*/ void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) { - while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID) { - checkEvents(); - } + checkEvents(); } /*------------------------------------------------------------------------*/ @@ -138,8 +136,11 @@ void OptionsMenu::execute() { openWindow(); while (!_vm->shouldQuit()) { - showContents(title1Sprites, true); - + // Show the dialog with a continually animating background + while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID) + showContents(title1Sprites, true); + if (_vm->shouldQuit()) + return; } } } @@ -157,7 +158,7 @@ void OptionsMenu::showTitles1(SpriteResource &sprites) { screen.restoreBackground(); sprites.draw(screen, frameNum); - while (events.timeElapsed() == 0) + while (events.timeElapsed() < 4) events.pollEventsAndWait(); } } @@ -356,12 +357,14 @@ void WorldOptionsMenu::openWindow() { void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) { Screen &screen = *_vm->_screen; EventsManager &events = *_vm->_events; - events.updateGameCounter(); + + // Draw the background frame in a continous cycle _bgFrame = ++_bgFrame % 5; - title1.draw(screen._windows[0], 0); - screen._windows[28].frame(); + title1.draw(screen._windows[0], _bgFrame); + // Draw the basic frame for the optitons menu and title text + screen._windows[28].frame(); screen._windows[28].writeString("\x0D\x01\003c\014dMight and Magic Options\n" "World of Xeen\x02\n" "\v117Copyright (c) 1993 NWC, Inc.\n" @@ -377,7 +380,11 @@ void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) { if (waitFlag) { screen._windows[0].update(); - SettingsBaseDialog::showContents(title1, true); + + while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID && + events.timeElapsed() < 3) { + checkEvents(); + } } } -- cgit v1.2.3 From def7e9f098436f64887bdc14944c6235e0a12cc1 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 1 Jan 2015 00:18:38 -1000 Subject: XEEN: Fix clicking to have Options menu appear --- engines/xeen/menus.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp index 68ef87a853..92badb9f81 100644 --- a/engines/xeen/menus.cpp +++ b/engines/xeen/menus.cpp @@ -158,8 +158,7 @@ void OptionsMenu::showTitles1(SpriteResource &sprites) { screen.restoreBackground(); sprites.draw(screen, frameNum); - while (events.timeElapsed() < 4) - events.pollEventsAndWait(); + events.wait(4, true); } } -- cgit v1.2.3 From 64ccc21cefefa585fe9227f453b5e370e6a62b8b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 1 Jan 2015 09:50:14 -1000 Subject: XEEN: Fix options menu to show correct buttons --- engines/xeen/resources.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 4da84c1d38..ba2889fc9d 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -195,13 +195,10 @@ bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEn void Resources::init(XeenEngine *vm) { Common::File f; - const char *ARCHIVES[3] = { "xeen", "dark", "intro" }; - for (int i = 0; i < 3; ++i) { - Common::String filename = Common::String::format("%s.cc", ARCHIVES[i]); - if (f.exists(filename)) { - SearchMan.add(ARCHIVES[i], new CCArchive(filename)); - } - } + if (vm->getGameID() != GType_Clouds) + SearchMan.add("dark", new CCArchive("dark.cc")); + SearchMan.add("xeen", new CCArchive("xeen.cc")); + SearchMan.add("intro", new CCArchive("intro.cc")); } /*------------------------------------------------------------------------*/ -- cgit v1.2.3 From fe48af7de5207cdc8a3e2ad769f6722b345b2877 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 1 Jan 2015 11:10:26 -1000 Subject: XEEN: Split up menus file into dialogs and dialogs_options --- engines/xeen/dialogs.cpp | 83 +++++++++ engines/xeen/dialogs.h | 78 ++++++++ engines/xeen/dialogs_options.cpp | 343 ++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_options.h | 89 +++++++++ engines/xeen/menus.cpp | 390 --------------------------------------- engines/xeen/menus.h | 133 ------------- engines/xeen/module.mk | 3 +- engines/xeen/xeen.cpp | 2 +- 8 files changed, 596 insertions(+), 525 deletions(-) create mode 100644 engines/xeen/dialogs.cpp create mode 100644 engines/xeen/dialogs.h create mode 100644 engines/xeen/dialogs_options.cpp create mode 100644 engines/xeen/dialogs_options.h delete mode 100644 engines/xeen/menus.cpp delete mode 100644 engines/xeen/menus.h (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp new file mode 100644 index 0000000000..1342353b9a --- /dev/null +++ b/engines/xeen/dialogs.cpp @@ -0,0 +1,83 @@ +/* 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/scummsys.h" +#include "xeen/dialogs.h" + +namespace Xeen { + +/** + * Saves the current list of buttons + */ +void Dialog::saveButtons() { + _savedButtons.push(_buttons); +} + +/* + * Clears the current list of defined buttons + */ +void Dialog::clearButtons() { + _buttons.clear(); +} + +void Dialog::restoreButtons() { + _buttons = _savedButtons.pop(); +} + +void Dialog::addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw = true) { + _buttons.push_back(DialogButton(bounds, c, sprites, draw)); +} + +void Dialog::checkEvents() { + EventsManager &events = *_vm->_events; + events.pollEventsAndWait(); + + if (events._leftButton) { + // Check whether any button is selected + events.debounceMouse(); + Common::Point pt = events._mousePos; + + for (uint i = 0; i < _buttons.size(); ++i) { + if (_buttons[i]._bounds.contains(pt)) { + _key = _buttons[i]._c; + return; + } + } + } else if (events.isKeyPending()) { + Common::KeyState keyState; + events.getKey(keyState); + if (keyState.ascii >= 32 && keyState.ascii <= 127) { + _key = keyState.ascii; + return; + } + } +} + +/*------------------------------------------------------------------------*/ + +void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) { + checkEvents(); +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h new file mode 100644 index 0000000000..21bf57c8e7 --- /dev/null +++ b/engines/xeen/dialogs.h @@ -0,0 +1,78 @@ +/* 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 XEEN_DIALOGS_H +#define XEEN_DIALOGS_H + +#include "common/array.h" +#include "common/stack.h" +#include "common/rect.h" +#include "xeen/xeen.h" + +namespace Xeen { + +class DialogButton { +public: + Common::Rect _bounds; + SpriteResource *_sprites; + char _c; + bool _draw; + + DialogButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw) : + _bounds(bounds), _c(c), _sprites(sprites), _draw(draw) {} + + DialogButton() : _c('\0'), _sprites(nullptr), _draw(false) {} +}; + +class Dialog { +private: + Common::Stack< Common::Array<DialogButton> > _savedButtons; +protected: + XeenEngine *_vm; + Common::Array<DialogButton> _buttons; + char _key; + + virtual void doScroll(bool drawFlag, bool doFade); + + void checkEvents(); +public: + Dialog(XeenEngine *vm): _vm(vm), _key('\0') {} + + void saveButtons(); + + void clearButtons(); + + void restoreButtons(); + + void addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw); +}; + +class SettingsBaseDialog : public Dialog { +protected: + virtual void showContents(SpriteResource &title1, bool mode); +public: + SettingsBaseDialog(XeenEngine *vm) : Dialog(vm) {} +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_H */ diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp new file mode 100644 index 0000000000..e4ebf27b79 --- /dev/null +++ b/engines/xeen/dialogs_options.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 "common/scummsys.h" +#include "xeen/dialogs_options.h" + +namespace Xeen { + +void OptionsMenu::show(XeenEngine *vm) { + OptionsMenu *menu; + + switch (vm->getGameID()) { + case GType_Clouds: + menu = new CloudsOptionsMenu(vm); + break; + case GType_DarkSide: + menu = new DarkSideOptionsMenu(vm); + break; + case GType_WorldOfXeen: + menu = new WorldOptionsMenu(vm); + break; + default: + error("Unsupported game"); + break; + } + + menu->execute(); + delete menu; +} + +void OptionsMenu::execute() { + SpriteResource special("special.icn"); + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + + File newBright("newbrigh.m"); + _vm->_sound->playMusic(newBright); + + screen._windows[28].setBounds(Common::Rect(72, 25, 248, 175)); + + Common::String title1, title2; + startup(title1, title2); + SpriteResource title1Sprites(title1), title2Sprites(title2); + + bool firstTime = true, doFade = true; + while (!_vm->shouldQuit()) { + setBackground(doFade); + events.setCursor(0); + + if (firstTime) { + firstTime = false; + warning("TODO: Read existing save file"); + } + + showTitles1(title1Sprites); + showTitles2(); + + clearButtons(); + setupButtons(&title2Sprites); + openWindow(); + + while (!_vm->shouldQuit()) { + // Show the dialog with a continually animating background + while (!_vm->shouldQuit() && _key == '\0') + showContents(title1Sprites, true); + if (_vm->shouldQuit()) + return; + + // Handle keypress + switch (toupper(_key)) { + case 'C': + case 'V': + // Show credits + break; + default: + break; + } + _key = '\0'; + } + } +} + +void OptionsMenu::showTitles1(SpriteResource &sprites) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + + int frameNum = 0; + while (!_vm->shouldQuit() && !events.isKeyMousePressed()) { + events.updateGameCounter(); + + frameNum = ++frameNum % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10); + screen.restoreBackground(); + sprites.draw(screen, frameNum); + + events.wait(4, true); + } +} + +void OptionsMenu::showTitles2() { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + SoundManager &sound = *_vm->_sound; + + File voc("elect.voc"); + SpriteResource titleSprites("title2b.raw"); + SpriteResource kludgeSprites("kludge.int"); + SpriteResource title2Sprites[8] = { + SpriteResource("title2b.int"), SpriteResource("title2c.int"), + SpriteResource("title2d.int"), SpriteResource("title2e.int"), + SpriteResource("title2f.int"), SpriteResource("title2g.int"), + SpriteResource("title2h.int"), SpriteResource("title2i.int"), + }; + + kludgeSprites.draw(screen, 0); + screen.saveBackground(); + sound.playSample(&voc, 0); + + for (int i = 0; i < 30 && !_vm->shouldQuit(); ++i) { + events.updateGameCounter(); + screen.restoreBackground(); + title2Sprites[i / 4].draw(screen, i % 4); + screen._windows[0].update(); + + if (i == 19) + sound.playSample(nullptr, 0); + + while (!_vm->shouldQuit() && events.timeElapsed() < 2) + events.pollEventsAndWait(); + } + + screen.restoreBackground(); + screen._windows[0].update(); +} + +void OptionsMenu::setupButtons(SpriteResource *buttons) { + addButton(Common::Rect(124, 87, 124 + 53, 87 + 10), 'S', buttons, false); + addButton(Common::Rect(126, 98, 126 + 47, 98 + 10), 'L', buttons, false); + addButton(Common::Rect(91, 110, 91 + 118, 110 + 10), 'C', buttons, false); + addButton(Common::Rect(85, 121, 85 + 131, 121 + 10), 'O', buttons, false); +} + +void WorldOptionsMenu::setupButtons(SpriteResource *buttons) { + addButton(Common::Rect(93, 53, 93 + 134, 53 + 20), 'S', buttons, true); + addButton(Common::Rect(93, 78, 93 + 134, 78 + 20), 'L', buttons, true); + addButton(Common::Rect(93, 103, 93 + 134, 103 + 20), 'C', buttons, true); + addButton(Common::Rect(93, 128, 93 + 134, 128 + 20), 'O', buttons, true); +} + +/*------------------------------------------------------------------------*/ + +void CloudsOptionsMenu::startup(Common::String &title1, Common::String &title2) { + title1 = "title1.int"; + title2 = "title1a.int"; +} + +/** +* Draws the scroll in the background +*/ +void Dialog::doScroll(bool drawFlag, bool doFade) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + const int SCROLL_L[8] = { 29, 23, 15, 251, 245, 233, 207, 185 }; + const int SCROLL_R[8] = { 165, 171, 198, 218, 228, 245, 264, 281 }; + + saveButtons(); + clearButtons(); + screen.saveBackground(); + + // Load hand vga files + SpriteResource *hand[16]; + for (int i = 0; i < 16; ++i) { + Common::String name = Common::String::format("hand%02u.vga"); + hand[i] = new SpriteResource(name); + } + + // Load marb vga files + SpriteResource *marb[5]; + for (int i = 1; i < 5; ++i) { + Common::String name = Common::String::format("marb%02u.vga"); + marb[i] = new SpriteResource(name); + } + + if (drawFlag) { + for (int i = 22; i > 0; --i) { + events.updateGameCounter(); + screen.restoreBackground(); + + if (i > 0 && i <= 14) { + hand[i - 1]->draw(screen, 0); + } else { + // TODO: Check '800h'.. horizontal reverse maybe? + hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 14], 0)); + marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 14], 0)); + } + + if (i <= 20) { + marb[i / 5]->draw(screen, i % 5); + } + + while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0) + _vm->_events->pollEventsAndWait(); + + screen._windows[0].update(); + if (i == 0 && doFade) + screen.fadeIn(2); + } + } else { + for (int i = 0; i < 22 && !events.isKeyMousePressed(); ++i) { + events.updateGameCounter(); + screen.restoreBackground(); + + if (i < 14) { + hand[i]->draw(screen, 0); + } + else { + // TODO: Check '800h'.. horizontal reverse maybe? + hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 7], 0)); + marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 7], 0)); + } + + if (i < 20) { + marb[i / 5]->draw(screen, i % 5); + } + + while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0) + _vm->_events->pollEventsAndWait(); + + screen._windows[0].update(); + if (i == 0 && doFade) + screen.fadeIn(2); + } + } + + if (drawFlag) { + hand[0]->draw(screen, 0); + marb[0]->draw(screen, 0); + } else { + screen.restoreBackground(); + } + + screen._windows[0].update(); + restoreButtons(); + + // Free resources + for (int i = 1; i < 5; ++i) + delete marb[i]; + for (int i = 0; i < 16; ++i) + delete hand[i]; +} + +/*------------------------------------------------------------------------*/ + +void DarkSideOptionsMenu::startup(Common::String &title1, Common::String &title2) { + title1 = "title2.int"; + title2 = "title2a.int"; +} + +/** +* Draws the scroll in the background +*/ +void DarkSideOptionsMenu::doScroll(bool drawFlag, bool doFade) { + if (doFade) { + _vm->_screen->fadeIn(2); + } +} + +void WorldOptionsMenu::startup(Common::String &title1, Common::String &title2) { + title1 = "world.int"; + title2 = "start.icn"; + + Screen &screen = *_vm->_screen; + screen.fadeOut(4); + screen.loadPalette("dark.pal"); + _vm->_events->clearEvents(); +} + +void WorldOptionsMenu::setBackground(bool doFade) { + Screen &screen = *_vm->_screen; + screen.loadBackground("world.raw"); + screen.saveBackground(); + + if (doFade) + screen.fadeIn(4); +} + +void WorldOptionsMenu::openWindow() { + _vm->_screen->_windows[28].open(); +} + +void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + events.updateGameCounter(); + + // Draw the background frame in a continous cycle + _bgFrame = ++_bgFrame % 5; + title1.draw(screen._windows[0], _bgFrame); + + // Draw the basic frame for the optitons menu and title text + screen._windows[28].frame(); + screen._windows[28].writeString("\x0D\x01\003c\014dMight and Magic Options\n" + "World of Xeen\x02\n" + "\v117Copyright (c) 1993 NWC, Inc.\n" + "All Rights Reserved\x01"); + + for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) { + DialogButton &btn = _buttons[btnIndex]; + if (btn._draw) { + btn._sprites->draw(screen._windows[0], btnIndex * 2, + Common::Point(btn._bounds.left, btn._bounds.top)); + } + } + + if (waitFlag) { + screen._windows[0].update(); + + while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID && + events.timeElapsed() < 3) { + checkEvents(); + } + } +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_options.h b/engines/xeen/dialogs_options.h new file mode 100644 index 0000000000..591ab5e043 --- /dev/null +++ b/engines/xeen/dialogs_options.h @@ -0,0 +1,89 @@ +/* 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 XEEN_DIALOGS_OPTIONS_H +#define XEEN_DIALOGS_OPTIONS_H + +#include "xeen/xeen.h" +#include "xeen/dialogs.h" + +namespace Xeen { + +class OptionsMenu : public SettingsBaseDialog { +private: + void execute(); +protected: + OptionsMenu(XeenEngine *vm) : SettingsBaseDialog(vm) {} +protected: + virtual void startup(Common::String &title1, Common::String &title2) = 0; + + virtual void setBackground(bool doFade) {} + + virtual void showTitles1(SpriteResource &sprites); + + virtual void showTitles2(); + + virtual void setupButtons(SpriteResource *buttons); + + virtual void openWindow() {} +public: + static void show(XeenEngine *vm); +}; + +class CloudsOptionsMenu : public OptionsMenu { +protected: + virtual void startup(Common::String &title1, Common::String &title2); +public: + CloudsOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {} +}; + +class DarkSideOptionsMenu : public OptionsMenu { +protected: + virtual void startup(Common::String &title1, Common::String &title2); + + virtual void doScroll(bool drawFlag, bool doFade); +public: + DarkSideOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {} +}; + +class WorldOptionsMenu : public DarkSideOptionsMenu { +private: + int _bgFrame; +protected: + virtual void startup(Common::String &title1, Common::String &title2); + + virtual void setBackground(bool doFade); + + virtual void showTitles2() {} + + virtual void setupButtons(SpriteResource *buttons); + + virtual void openWindow(); + + virtual void showContents(SpriteResource &title1, bool mode); +public: + WorldOptionsMenu(XeenEngine *vm) : DarkSideOptionsMenu(vm), _bgFrame(0) {} +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_H */ diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp deleted file mode 100644 index 92badb9f81..0000000000 --- a/engines/xeen/menus.cpp +++ /dev/null @@ -1,390 +0,0 @@ -/* 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/scummsys.h" -#include "xeen/menus.h" - -namespace Xeen { - -/** - * Saves the current list of buttons - */ -void Dialog::saveButtons() { - _savedButtons.push(_buttons); -} - -/* - * Clears the current list of defined buttons - */ -void Dialog::clearButtons() { - _buttons.clear(); -} - -void Dialog::restoreButtons() { - _buttons = _savedButtons.pop(); -} - -void Dialog::addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw = true) { - _buttons.push_back(DialogButton(bounds, c, sprites, draw)); -} - -void Dialog::checkEvents() { - EventsManager &events = *_vm->_events; - events.pollEventsAndWait(); - - if (events._leftButton) { - // Check whether any button is selected - events.debounceMouse(); - Common::Point pt = events._mousePos; - - for (uint i = 0; i < _buttons.size(); ++i) { - if (_buttons[i]._bounds.contains(pt)) { - _key = _buttons[i]._c; - return; - } - } - } else if (events.isKeyPending()) { - Common::KeyState keyState; - events.getKey(keyState); - if (keyState.ascii >= 32 && keyState.ascii <= 127) { - _key = keyState.ascii; - return; - } - } -} - -/*------------------------------------------------------------------------*/ - -void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) { - checkEvents(); -} - -/*------------------------------------------------------------------------*/ - -void OptionsMenu::show(XeenEngine *vm) { - OptionsMenu *menu; - - switch (vm->getGameID()) { - case GType_Clouds: - menu = new CloudsOptionsMenu(vm); - break; - case GType_DarkSide: - menu = new DarkSideOptionsMenu(vm); - break; - case GType_WorldOfXeen: - menu = new WorldOptionsMenu(vm); - break; - default: - error("Unsupported game"); - break; - } - - menu->execute(); - delete menu; -} - -void OptionsMenu::execute() { - SpriteResource special("special.icn"); - Screen &screen = *_vm->_screen; - EventsManager &events = *_vm->_events; - - File newBright("newbrigh.m"); - _vm->_sound->playMusic(newBright); - - screen._windows[28].setBounds(Common::Rect(72, 25, 248, 175)); - - Common::String title1, title2; - startup(title1, title2); - SpriteResource title1Sprites(title1), title2Sprites(title2); - - bool firstTime = true, doFade = true; - while (!_vm->shouldQuit()) { - setBackground(doFade); - events.setCursor(0); - - if (firstTime) { - firstTime = false; - warning("TODO: Read existing save file"); - } - - while (!_vm->shouldQuit()) { - showTitles1(title1Sprites); - showTitles2(); - - reopen: - clearButtons(); - setupButtons(&title2Sprites); - openWindow(); - - while (!_vm->shouldQuit()) { - // Show the dialog with a continually animating background - while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID) - showContents(title1Sprites, true); - if (_vm->shouldQuit()) - return; - } - } - } -} - -void OptionsMenu::showTitles1(SpriteResource &sprites) { - Screen &screen = *_vm->_screen; - EventsManager &events = *_vm->_events; - - int frameNum = 0; - while (!_vm->shouldQuit() && !events.isKeyMousePressed()) { - events.updateGameCounter(); - - frameNum = ++frameNum % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10); - screen.restoreBackground(); - sprites.draw(screen, frameNum); - - events.wait(4, true); - } -} - -void OptionsMenu::showTitles2() { - Screen &screen = *_vm->_screen; - EventsManager &events = *_vm->_events; - SoundManager &sound = *_vm->_sound; - - File voc("elect.voc"); - SpriteResource titleSprites("title2b.raw"); - SpriteResource kludgeSprites("kludge.int"); - SpriteResource title2Sprites[8] = { - SpriteResource("title2b.int"), SpriteResource("title2c.int"), - SpriteResource("title2d.int"), SpriteResource("title2e.int"), - SpriteResource("title2f.int"), SpriteResource("title2g.int"), - SpriteResource("title2h.int"), SpriteResource("title2i.int"), - }; - - kludgeSprites.draw(screen, 0); - screen.saveBackground(); - sound.playSample(&voc, 0); - - for (int i = 0; i < 30 && !_vm->shouldQuit(); ++i) { - events.updateGameCounter(); - screen.restoreBackground(); - title2Sprites[i / 4].draw(screen, i % 4); - screen._windows[0].update(); - - if (i == 19) - sound.playSample(nullptr, 0); - - while (!_vm->shouldQuit() && events.timeElapsed() < 2) - events.pollEventsAndWait(); - } - - screen.restoreBackground(); - screen._windows[0].update(); -} - -void OptionsMenu::setupButtons(SpriteResource *buttons) { - addButton(Common::Rect(124, 87, 124 + 53, 87 + 10), 'S', buttons, false); - addButton(Common::Rect(126, 98, 126 + 47, 98 + 10), 'L', buttons, false); - addButton(Common::Rect(91, 110, 91 + 118, 110 + 10), 'C', buttons, false); - addButton(Common::Rect(85, 121, 85 + 131, 121 + 10), 'O', buttons, false); -} - -void WorldOptionsMenu::setupButtons(SpriteResource *buttons) { - addButton(Common::Rect(93, 53, 93 + 134, 53 + 20), 'S', buttons, true); - addButton(Common::Rect(93, 78, 93 + 134, 78 + 20), 'L', buttons, true); - addButton(Common::Rect(93, 103, 93 + 134, 103 + 20), 'C', buttons, true); - addButton(Common::Rect(93, 128, 93 + 134, 128 + 20), 'O', buttons, true); -} - -/*------------------------------------------------------------------------*/ - -void CloudsOptionsMenu::startup(Common::String &title1, Common::String &title2) { - title1 = "title1.int"; - title2 = "title1a.int"; -} - -/** -* Draws the scroll in the background -*/ -void Dialog::doScroll(bool drawFlag, bool doFade) { - Screen &screen = *_vm->_screen; - EventsManager &events = *_vm->_events; - const int SCROLL_L[8] = { 29, 23, 15, 251, 245, 233, 207, 185 }; - const int SCROLL_R[8] = { 165, 171, 198, 218, 228, 245, 264, 281 }; - - saveButtons(); - clearButtons(); - screen.saveBackground(); - - // Load hand vga files - SpriteResource *hand[16]; - for (int i = 0; i < 16; ++i) { - Common::String name = Common::String::format("hand%02u.vga"); - hand[i] = new SpriteResource(name); - } - - // Load marb vga files - SpriteResource *marb[5]; - for (int i = 1; i < 5; ++i) { - Common::String name = Common::String::format("marb%02u.vga"); - marb[i] = new SpriteResource(name); - } - - if (drawFlag) { - for (int i = 22; i > 0; --i) { - events.updateGameCounter(); - screen.restoreBackground(); - - if (i > 0 && i <= 14) { - hand[i - 1]->draw(screen, 0); - } else { - // TODO: Check '800h'.. horizontal reverse maybe? - hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 14], 0)); - marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 14], 0)); - } - - if (i <= 20) { - marb[i / 5]->draw(screen, i % 5); - } - - while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0) - _vm->_events->pollEventsAndWait(); - - screen._windows[0].update(); - if (i == 0 && doFade) - screen.fadeIn(2); - } - } else { - for (int i = 0; i < 22 && !events.isKeyMousePressed(); ++i) { - events.updateGameCounter(); - screen.restoreBackground(); - - if (i < 14) { - hand[i]->draw(screen, 0); - } - else { - // TODO: Check '800h'.. horizontal reverse maybe? - hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 7], 0)); - marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 7], 0)); - } - - if (i < 20) { - marb[i / 5]->draw(screen, i % 5); - } - - while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0) - _vm->_events->pollEventsAndWait(); - - screen._windows[0].update(); - if (i == 0 && doFade) - screen.fadeIn(2); - } - } - - if (drawFlag) { - hand[0]->draw(screen, 0); - marb[0]->draw(screen, 0); - } else { - screen.restoreBackground(); - } - - screen._windows[0].update(); - restoreButtons(); - - // Free resources - for (int i = 1; i < 5; ++i) - delete marb[i]; - for (int i = 0; i < 16; ++i) - delete hand[i]; -} - -/*------------------------------------------------------------------------*/ - -void DarkSideOptionsMenu::startup(Common::String &title1, Common::String &title2) { - title1 = "title2.int"; - title2 = "title2a.int"; -} - -/** -* Draws the scroll in the background -*/ -void DarkSideOptionsMenu::doScroll(bool drawFlag, bool doFade) { - if (doFade) { - _vm->_screen->fadeIn(2); - } -} - -void WorldOptionsMenu::startup(Common::String &title1, Common::String &title2) { - title1 = "world.int"; - title2 = "start.icn"; - - Screen &screen = *_vm->_screen; - screen.fadeOut(4); - screen.loadPalette("dark.pal"); - _vm->_events->clearEvents(); -} - -void WorldOptionsMenu::setBackground(bool doFade) { - Screen &screen = *_vm->_screen; - screen.loadBackground("world.raw"); - screen.saveBackground(); - - if (doFade) - screen.fadeIn(4); -} - -void WorldOptionsMenu::openWindow() { - _vm->_screen->_windows[28].open(); -} - -void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) { - Screen &screen = *_vm->_screen; - EventsManager &events = *_vm->_events; - events.updateGameCounter(); - - // Draw the background frame in a continous cycle - _bgFrame = ++_bgFrame % 5; - title1.draw(screen._windows[0], _bgFrame); - - // Draw the basic frame for the optitons menu and title text - screen._windows[28].frame(); - screen._windows[28].writeString("\x0D\x01\003c\014dMight and Magic Options\n" - "World of Xeen\x02\n" - "\v117Copyright (c) 1993 NWC, Inc.\n" - "All Rights Reserved\x01"); - - for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) { - DialogButton &btn = _buttons[btnIndex]; - if (btn._draw) { - btn._sprites->draw(screen._windows[0], btnIndex * 2, - Common::Point(btn._bounds.left, btn._bounds.top)); - } - } - - if (waitFlag) { - screen._windows[0].update(); - - while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID && - events.timeElapsed() < 3) { - checkEvents(); - } - } -} - -} // End of namespace Xeen diff --git a/engines/xeen/menus.h b/engines/xeen/menus.h deleted file mode 100644 index 65e3553110..0000000000 --- a/engines/xeen/menus.h +++ /dev/null @@ -1,133 +0,0 @@ -/* 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 XEEN_MENUS_H -#define XEEN_MENUS_H - -#include "common/array.h" -#include "common/stack.h" -#include "common/rect.h" -#include "xeen/xeen.h" - -namespace Xeen { - -class DialogButton { -public: - Common::Rect _bounds; - SpriteResource *_sprites; - char _c; - bool _draw; - - DialogButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw) : - _bounds(bounds), _c(c), _sprites(sprites), _draw(draw) {} - - DialogButton() : _c('\0'), _sprites(nullptr), _draw(false) {} -}; - -class Dialog { -private: - Common::Stack< Common::Array<DialogButton> > _savedButtons; -protected: - XeenEngine *_vm; - Common::Array<DialogButton> _buttons; - char _key; - - virtual void doScroll(bool drawFlag, bool doFade); - - void checkEvents(); -public: - Dialog(XeenEngine *vm): _vm(vm), _key('\0') {} - - void saveButtons(); - - void clearButtons(); - - void restoreButtons(); - - void addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw); -}; - -class SettingsBaseDialog : public Dialog { -protected: - virtual void showContents(SpriteResource &title1, bool mode); -public: - SettingsBaseDialog(XeenEngine *vm) : Dialog(vm) {} -}; -class OptionsMenu : public SettingsBaseDialog { -private: - void execute(); -protected: - OptionsMenu(XeenEngine *vm) : SettingsBaseDialog(vm) {} -protected: - virtual void startup(Common::String &title1, Common::String &title2) = 0; - - virtual void setBackground(bool doFade) {} - - virtual void showTitles1(SpriteResource &sprites); - - virtual void showTitles2(); - - virtual void setupButtons(SpriteResource *buttons); - - virtual void openWindow() {} -public: - static void show(XeenEngine *vm); -}; - -class CloudsOptionsMenu : public OptionsMenu { -protected: - virtual void startup(Common::String &title1, Common::String &title2); -public: - CloudsOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {} -}; - -class DarkSideOptionsMenu : public OptionsMenu { -protected: - virtual void startup(Common::String &title1, Common::String &title2); - - virtual void doScroll(bool drawFlag, bool doFade); -public: - DarkSideOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {} -}; - -class WorldOptionsMenu : public DarkSideOptionsMenu { -private: - int _bgFrame; -protected: - virtual void startup(Common::String &title1, Common::String &title2); - - virtual void setBackground(bool doFade); - - virtual void showTitles2() {} - - virtual void setupButtons(SpriteResource *buttons); - - virtual void openWindow(); - - virtual void showContents(SpriteResource &title1, bool mode); -public: - WorldOptionsMenu(XeenEngine *vm) : DarkSideOptionsMenu(vm), _bgFrame(0) {} -}; - -} // End of namespace Xeen - -#endif /* XEEN_MENUS_H */ diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 9d7b0ebb70..99eb98174e 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -6,9 +6,10 @@ MODULE_OBJS := \ worldofxeen\worldofxeen_game.o \ debugger.o \ detection.o \ + dialogs.o \ + dialogs_options.o \ events.o \ font.o \ - menus.o \ resdata.o \ resources.o \ screen.o \ diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 1027572c67..cbdb6f3104 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -28,7 +28,7 @@ #include "graphics/scaler.h" #include "graphics/thumbnail.h" #include "xeen/xeen.h" -#include "xeen/menus.h" +#include "xeen/dialogs_options.h" #include "xeen/resources.h" namespace Xeen { -- cgit v1.2.3 From aa3965cd5dcdf0d774f4798b003c8089e3bcdc7e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 1 Jan 2015 11:32:56 -1000 Subject: XEEN: Beginnings of credits screen --- engines/xeen/dialogs.cpp | 30 +++++++++++++++++++++++++++++ engines/xeen/dialogs.h | 9 +++++++++ engines/xeen/dialogs_options.cpp | 17 +++++++---------- engines/xeen/resdata.cpp | 41 ++++++++++++++++++++++++++++++++++++++++ engines/xeen/resdata.h | 4 ++++ 5 files changed, 91 insertions(+), 10 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index 1342353b9a..b550cf2f01 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -22,6 +22,7 @@ #include "common/scummsys.h" #include "xeen/dialogs.h" +#include "xeen/resdata.h" namespace Xeen { @@ -80,4 +81,33 @@ void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) { /*------------------------------------------------------------------------*/ +void CreditsScreen::show(XeenEngine *vm) { + CreditsScreen *dlg = new CreditsScreen(vm); + dlg->execute(); + delete dlg; +} + +void CreditsScreen::execute() { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + + // Handle drawing the credits screen + doScroll(true, false); + screen._windows[28].close(); + + screen.loadBackground("marb.raw"); + screen._windows[0].writeString(CREDITS); + doScroll(false, false); + + events.setCursor(0); + screen._windows[0].update(); + clearButtons(); + + // Wait for keypress + while (!events.isKeyMousePressed()) + events.pollEventsAndWait(); + + doScroll(true, false); +} + } // End of namespace Xeen diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h index 21bf57c8e7..9810380081 100644 --- a/engines/xeen/dialogs.h +++ b/engines/xeen/dialogs.h @@ -73,6 +73,15 @@ public: SettingsBaseDialog(XeenEngine *vm) : Dialog(vm) {} }; +class CreditsScreen: public Dialog { +private: + CreditsScreen(XeenEngine *vm) : Dialog(vm) {} + + void execute(); +public: + static void show(XeenEngine *vm); +}; + } // End of namespace Xeen #endif /* XEEN_DIALOGS_H */ diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp index e4ebf27b79..e7f296c9a4 100644 --- a/engines/xeen/dialogs_options.cpp +++ b/engines/xeen/dialogs_options.cpp @@ -22,6 +22,7 @@ #include "common/scummsys.h" #include "xeen/dialogs_options.h" +#include "xeen/resdata.h" namespace Xeen { @@ -86,14 +87,13 @@ void OptionsMenu::execute() { return; // Handle keypress - switch (toupper(_key)) { - case 'C': - case 'V': + char key = toupper(_key); + if (key == 'C' || key == 'V') { // Show credits - break; - default: + CreditsScreen::show(_vm); break; } + _key = '\0'; } } @@ -188,7 +188,7 @@ void Dialog::doScroll(bool drawFlag, bool doFade) { // Load hand vga files SpriteResource *hand[16]; for (int i = 0; i < 16; ++i) { - Common::String name = Common::String::format("hand%02u.vga"); + Common::String name = Common::String::format("hand%02u.vga", i); hand[i] = new SpriteResource(name); } @@ -317,10 +317,7 @@ void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) { // Draw the basic frame for the optitons menu and title text screen._windows[28].frame(); - screen._windows[28].writeString("\x0D\x01\003c\014dMight and Magic Options\n" - "World of Xeen\x02\n" - "\v117Copyright (c) 1993 NWC, Inc.\n" - "All Rights Reserved\x01"); + screen._windows[28].writeString(OPTIONS_TITLE); for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) { DialogButton &btn = _buttons[btnIndex]; diff --git a/engines/xeen/resdata.cpp b/engines/xeen/resdata.cpp index 1cdd3ac0fb..b9309b4adb 100644 --- a/engines/xeen/resdata.cpp +++ b/engines/xeen/resdata.cpp @@ -25,6 +25,47 @@ namespace Xeen { +const char *const CREDITS = + "\013012\010000\003c\01435Designed and Directed By:\n" + "\01417Jon Van Caneghem\003l\n" + "\n" + "\t025\01435Programming:\n" + "\t035\01417Mark Caldwell\n" + "\t035Dave Hathaway\n" + "\n" + "\t025\01435Sound System & FX:\n" + "\t035\01417Mike Heilemann\n" + "\n" + "\t025\01435Music & Speech:\n" + "\t035\01417Tim Tully\n" + "\n" + "\t025\01435Writing:\n" + "\t035\01417Paul Rattner\n" + "\t035Debbie Van Caneghem\n" + "\t035Jon Van Caneghem\013012\n" + "\n" + "\n" + "\t180\01435Graphics:\n" + "\t190\01417Jonathan P. Gwyn\n" + "\t190Bonita Long-Hemsath\n" + "\t190Julia Ulano\n" + "\t190Ricardo Barrera\n" + "\n" + "\t180\01435Testing:\n" + "\t190\01417Benjamin Bent\n" + "\t190Christian Dailey\n" + "\t190Mario Escamilla\n" + "\t190Marco Hunter\n" + "\t190Robert J. Lupo\n" + "\t190Clayton Retzer\n" + "\t190David Vela\003c"; + +const char *const OPTIONS_TITLE = + "\x0D\x01\003c\014dMight and Magic Options\n" + "World of Xeen\x02\n" + "\v117Copyright (c) 1993 NWC, Inc.\n" + "All Rights Reserved\x01"; + const byte SYMBOLS[20][64] = { { // 0 0x00, 0x00, 0xA8, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x00, 0xA8, 0x9E, 0x9C, 0x9C, 0x9E, 0x9E, 0x9E, diff --git a/engines/xeen/resdata.h b/engines/xeen/resdata.h index deb6e589be..3c549fc225 100644 --- a/engines/xeen/resdata.h +++ b/engines/xeen/resdata.h @@ -28,6 +28,10 @@ namespace Xeen { +extern const char *const CREDITS; + +extern const char *const OPTIONS_TITLE; + extern const byte SYMBOLS[20][64]; extern const byte TEXT_COLORS[40][4]; -- cgit v1.2.3 From b2f1282aeb7f405f265afac3d601459f4cfebf6d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 1 Jan 2015 11:46:22 -1000 Subject: XEEN: Credits screen now working --- engines/xeen/dialogs.cpp | 105 +++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs.h | 2 +- engines/xeen/dialogs_options.cpp | 108 +-------------------------------------- engines/xeen/dialogs_options.h | 2 - engines/xeen/screen.cpp | 17 +++--- engines/xeen/screen.h | 2 - 6 files changed, 117 insertions(+), 119 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index b550cf2f01..cdc6d5ba40 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -73,6 +73,111 @@ void Dialog::checkEvents() { } } + +/** +* Draws the scroll in the background +*/ +void Dialog::doScroll(bool drawFlag, bool doFade) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + + if (_vm->getGameID() != GType_Clouds) { + if (doFade) { + _vm->_screen->fadeIn(2); + } + return; + } + + const int SCROLL_L[8] = { 29, 23, 15, 251, 245, 233, 207, 185 }; + const int SCROLL_R[8] = { 165, 171, 198, 218, 228, 245, 264, 281 }; + + saveButtons(); + clearButtons(); + screen.saveBackground(); + + // Load hand vga files + SpriteResource *hand[16]; + for (int i = 0; i < 16; ++i) { + Common::String name = Common::String::format("hand%02u.vga", i); + hand[i] = new SpriteResource(name); + } + + // Load marb vga files + SpriteResource *marb[5]; + for (int i = 1; i < 5; ++i) { + Common::String name = Common::String::format("marb%02u.vga"); + marb[i] = new SpriteResource(name); + } + + if (drawFlag) { + for (int i = 22; i > 0; --i) { + events.updateGameCounter(); + screen.restoreBackground(); + + if (i > 0 && i <= 14) { + hand[i - 1]->draw(screen, 0); + } + else { + // TODO: Check '800h'.. horizontal reverse maybe? + hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 14], 0)); + marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 14], 0)); + } + + if (i <= 20) { + marb[i / 5]->draw(screen, i % 5); + } + + while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0) + _vm->_events->pollEventsAndWait(); + + screen._windows[0].update(); + if (i == 0 && doFade) + screen.fadeIn(2); + } + } else { + for (int i = 0; i < 22 && !events.isKeyMousePressed(); ++i) { + events.updateGameCounter(); + screen.restoreBackground(); + + if (i < 14) { + hand[i]->draw(screen, 0); + } else { + // TODO: Check '800h'.. horizontal reverse maybe? + hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 7], 0)); + marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 7], 0)); + } + + if (i < 20) { + marb[i / 5]->draw(screen, i % 5); + } + + while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0) + _vm->_events->pollEventsAndWait(); + + screen._windows[0].update(); + if (i == 0 && doFade) + screen.fadeIn(2); + } + } + + if (drawFlag) { + hand[0]->draw(screen, 0); + marb[0]->draw(screen, 0); + } + else { + screen.restoreBackground(); + } + + screen._windows[0].update(); + restoreButtons(); + + // Free resources + for (int i = 1; i < 5; ++i) + delete marb[i]; + for (int i = 0; i < 16; ++i) + delete hand[i]; +} + /*------------------------------------------------------------------------*/ void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) { diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h index 9810380081..1f8f2fb624 100644 --- a/engines/xeen/dialogs.h +++ b/engines/xeen/dialogs.h @@ -51,7 +51,7 @@ protected: Common::Array<DialogButton> _buttons; char _key; - virtual void doScroll(bool drawFlag, bool doFade); + void doScroll(bool drawFlag, bool doFade); void checkEvents(); public: diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp index e7f296c9a4..a92fd59715 100644 --- a/engines/xeen/dialogs_options.cpp +++ b/engines/xeen/dialogs_options.cpp @@ -88,13 +88,13 @@ void OptionsMenu::execute() { // Handle keypress char key = toupper(_key); + _key = '\0'; + if (key == 'C' || key == 'V') { // Show credits CreditsScreen::show(_vm); break; } - - _key = '\0'; } } } @@ -172,101 +172,6 @@ void CloudsOptionsMenu::startup(Common::String &title1, Common::String &title2) title2 = "title1a.int"; } -/** -* Draws the scroll in the background -*/ -void Dialog::doScroll(bool drawFlag, bool doFade) { - Screen &screen = *_vm->_screen; - EventsManager &events = *_vm->_events; - const int SCROLL_L[8] = { 29, 23, 15, 251, 245, 233, 207, 185 }; - const int SCROLL_R[8] = { 165, 171, 198, 218, 228, 245, 264, 281 }; - - saveButtons(); - clearButtons(); - screen.saveBackground(); - - // Load hand vga files - SpriteResource *hand[16]; - for (int i = 0; i < 16; ++i) { - Common::String name = Common::String::format("hand%02u.vga", i); - hand[i] = new SpriteResource(name); - } - - // Load marb vga files - SpriteResource *marb[5]; - for (int i = 1; i < 5; ++i) { - Common::String name = Common::String::format("marb%02u.vga"); - marb[i] = new SpriteResource(name); - } - - if (drawFlag) { - for (int i = 22; i > 0; --i) { - events.updateGameCounter(); - screen.restoreBackground(); - - if (i > 0 && i <= 14) { - hand[i - 1]->draw(screen, 0); - } else { - // TODO: Check '800h'.. horizontal reverse maybe? - hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 14], 0)); - marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 14], 0)); - } - - if (i <= 20) { - marb[i / 5]->draw(screen, i % 5); - } - - while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0) - _vm->_events->pollEventsAndWait(); - - screen._windows[0].update(); - if (i == 0 && doFade) - screen.fadeIn(2); - } - } else { - for (int i = 0; i < 22 && !events.isKeyMousePressed(); ++i) { - events.updateGameCounter(); - screen.restoreBackground(); - - if (i < 14) { - hand[i]->draw(screen, 0); - } - else { - // TODO: Check '800h'.. horizontal reverse maybe? - hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 7], 0)); - marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 7], 0)); - } - - if (i < 20) { - marb[i / 5]->draw(screen, i % 5); - } - - while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0) - _vm->_events->pollEventsAndWait(); - - screen._windows[0].update(); - if (i == 0 && doFade) - screen.fadeIn(2); - } - } - - if (drawFlag) { - hand[0]->draw(screen, 0); - marb[0]->draw(screen, 0); - } else { - screen.restoreBackground(); - } - - screen._windows[0].update(); - restoreButtons(); - - // Free resources - for (int i = 1; i < 5; ++i) - delete marb[i]; - for (int i = 0; i < 16; ++i) - delete hand[i]; -} - /*------------------------------------------------------------------------*/ void DarkSideOptionsMenu::startup(Common::String &title1, Common::String &title2) { @@ -274,15 +179,6 @@ void DarkSideOptionsMenu::startup(Common::String &title1, Common::String &title2 title2 = "title2a.int"; } -/** -* Draws the scroll in the background -*/ -void DarkSideOptionsMenu::doScroll(bool drawFlag, bool doFade) { - if (doFade) { - _vm->_screen->fadeIn(2); - } -} - void WorldOptionsMenu::startup(Common::String &title1, Common::String &title2) { title1 = "world.int"; title2 = "start.icn"; diff --git a/engines/xeen/dialogs_options.h b/engines/xeen/dialogs_options.h index 591ab5e043..7a933fdea6 100644 --- a/engines/xeen/dialogs_options.h +++ b/engines/xeen/dialogs_options.h @@ -59,8 +59,6 @@ public: class DarkSideOptionsMenu : public OptionsMenu { protected: virtual void startup(Common::String &title1, Common::String &title2); - - virtual void doScroll(bool drawFlag, bool doFade); public: DarkSideOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {} }; diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 6d5caae35f..f3cbabcfdd 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -60,7 +60,7 @@ void Window::open() { } void Window::open2() { - _dirtyRects.push(_bounds); + addDirtyRect(_bounds); frame(); fill(); } @@ -125,7 +125,6 @@ void Window::close() { // Update any remaining pending changes to the screen and free // the window's internal surface storage update(); - free(); // Remove the window from the stack and flag it as now disabled for (uint i = 0; i < _vm->_screen->_windowStack.size(); ++i) { @@ -142,17 +141,18 @@ void Window::close() { } /** - * Pushes any pending changes for the window to the screen + * Update the window */ void Window::update() { - while (!_dirtyRects.empty()) { - Common::Rect r = _dirtyRects.pop(); - blitTo(*_vm->_screen, Common::Point(_bounds.left, _bounds.top)); - } + // Since all window drawing is done on the screen surface anyway, + // there's nothing that needs to be updated here } +/** + * Adds an area that requires redrawing on the next frame update + */ void Window::addDirtyRect(const Common::Rect &r) { - _dirtyRects.push(r); + _vm->_screen->addDirtyRect(r); } /** @@ -319,6 +319,7 @@ void Screen::loadBackground(const Common::String &name) { assert(f.size() == (SCREEN_WIDTH * SCREEN_HEIGHT)); f.read((byte *)getPixels(), SCREEN_WIDTH * SCREEN_HEIGHT); + addDirtyRect(Common::Rect(0, 0, this->w, this->h)); } /** diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 41b2821c29..fd8a50968f 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -26,7 +26,6 @@ #include "common/scummsys.h" #include "common/system.h" #include "common/array.h" -#include "common/queue.h" #include "common/rect.h" #include "xeen/font.h" #include "xeen/xsurface.h" @@ -51,7 +50,6 @@ private: int _xLo, _xHi; int _ycL, _ycH; bool _enabled; - Common::Queue<Common::Rect> _dirtyRects; void open2(); public: -- cgit v1.2.3 From 5135439bbd64289e4c6c780f4b4da03ce40e75be Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 1 Jan 2015 14:57:56 -1000 Subject: XEEN: Reorganisation of resource, sprite, and cc file class files --- engines/xeen/dialogs.cpp | 2 +- engines/xeen/dialogs_options.cpp | 5 +- engines/xeen/events.h | 2 +- engines/xeen/files.cpp | 214 +++++++++++++++ engines/xeen/files.h | 58 ++++ engines/xeen/font.cpp | 2 +- engines/xeen/module.mk | 2 + engines/xeen/resdata.cpp | 235 ---------------- engines/xeen/resdata.h | 41 --- engines/xeen/resources.cpp | 562 ++++++++++++++------------------------- engines/xeen/resources.h | 82 +----- engines/xeen/sound.h | 2 +- engines/xeen/sprites.cpp | 201 ++++++++++++++ engines/xeen/sprites.h | 87 ++++++ engines/xeen/xeen.cpp | 4 +- engines/xeen/xsurface.cpp | 2 +- 16 files changed, 787 insertions(+), 714 deletions(-) create mode 100644 engines/xeen/files.cpp create mode 100644 engines/xeen/files.h delete mode 100644 engines/xeen/resdata.cpp delete mode 100644 engines/xeen/resdata.h create mode 100644 engines/xeen/sprites.cpp create mode 100644 engines/xeen/sprites.h (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index cdc6d5ba40..4d1a87647d 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -22,7 +22,7 @@ #include "common/scummsys.h" #include "xeen/dialogs.h" -#include "xeen/resdata.h" +#include "xeen/resources.h" namespace Xeen { diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp index a92fd59715..e85a4af51d 100644 --- a/engines/xeen/dialogs_options.cpp +++ b/engines/xeen/dialogs_options.cpp @@ -22,7 +22,7 @@ #include "common/scummsys.h" #include "xeen/dialogs_options.h" -#include "xeen/resdata.h" +#include "xeen/resources.h" namespace Xeen { @@ -94,6 +94,9 @@ void OptionsMenu::execute() { // Show credits CreditsScreen::show(_vm); break; + } else if (key == 27) { + // Hide the options menu + break; } } } diff --git a/engines/xeen/events.h b/engines/xeen/events.h index 6183b75105..5a9faf14d8 100644 --- a/engines/xeen/events.h +++ b/engines/xeen/events.h @@ -25,7 +25,7 @@ #include "common/scummsys.h" #include "common/events.h" -#include "xeen/resources.h" +#include "xeen/sprites.h" namespace Xeen { diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp new file mode 100644 index 0000000000..27bbf6e399 --- /dev/null +++ b/engines/xeen/files.cpp @@ -0,0 +1,214 @@ +/* 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/scummsys.h" +#include "common/archive.h" +#include "common/memstream.h" +#include "common/textconsole.h" +#include "xeen/xeen.h" +#include "xeen/files.h" + +namespace Xeen { + +/** + * Xeen CC file implementation + */ +class CCArchive : public Common::Archive { +private: + /** + * Details of a single entry in a CC file index + */ + struct CCEntry { + uint16 _id; + uint32 _offset; + uint16 _size; + + CCEntry() : _id(0), _offset(0), _size(0) {} + CCEntry(uint16 id, uint32 offset, uint32 size) + : _id(id), _offset(offset), _size(size) { + } + }; + + Common::Array<CCEntry> _index; + Common::String _filename; + + uint16 convertNameToId(const Common::String &resourceName) const; + + void loadIndex(Common::SeekableReadStream *stream); + + bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const; +public: + CCArchive(const Common::String &filename); + virtual ~CCArchive(); + + // Archive implementation + virtual bool hasFile(const Common::String &name) const; + virtual int listMembers(Common::ArchiveMemberList &list) const; + virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const; + virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; +}; + +CCArchive::CCArchive(const Common::String &filename): _filename(filename) { + File f(filename); + loadIndex(&f); +} + +CCArchive::~CCArchive() { +} + +// Archive implementation +bool CCArchive::hasFile(const Common::String &name) const { + CCEntry ccEntry; + return getHeaderEntry(name, ccEntry); +} + +int CCArchive::listMembers(Common::ArchiveMemberList &list) const { + // CC files don't maintain the original filenames, so we can't list it + return 0; +} + +const Common::ArchiveMemberPtr CCArchive::getMember(const Common::String &name) const { + if (!hasFile(name)) + return Common::ArchiveMemberPtr(); + + return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this)); +} + +Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::String &name) const { + CCEntry ccEntry; + + if (getHeaderEntry(name, ccEntry)) { + // Open the correct CC file + Common::File f; + if (!f.open(_filename)) + error("Could not open CC file"); + + // Read in the data for the specific resource + f.seek(ccEntry._offset); + byte *data = new byte[ccEntry._size]; + f.read(data, ccEntry._size); + + // Decrypt the data + for (int i = 0; i < ccEntry._size; ++i) + data[i] ^= 0x35; + + // Return the data as a stream + return new Common::MemoryReadStream(data, ccEntry._size, DisposeAfterUse::YES); + } + + return nullptr; +} + +/** + * Hash a given filename to produce the Id that represents it + */ +uint16 CCArchive::convertNameToId(const Common::String &resourceName) const { + if (resourceName.empty()) + return 0xffff; + + Common::String name = resourceName; + name.toUppercase(); + + const byte *msgP = (const byte *)name.c_str(); + int total = *msgP++; + for (; *msgP; total += *msgP++) { + // Rotate the bits in 'total' right 7 places + total = (total & 0x007F) << 9 | (total & 0xFF80) >> 7; + } + + return total; +} + +/** + * Load the index of a given CC file + */ +void CCArchive::loadIndex(Common::SeekableReadStream *stream) { + int count = stream->readUint16LE(); + + // Read in the data for the archive's index + byte *rawIndex = new byte[count * 8]; + stream->read(rawIndex, count * 8); + + // Decrypt the index + int ah = 0xac; + for (int i = 0; i < count * 8; ++i) { + rawIndex[i] = (byte)(((rawIndex[i] << 2 | rawIndex[i] >> 6) + ah) & 0xff); + ah += 0x67; + } + + // Extract the index data into entry structures + _index.reserve(count); + const byte *entryP = &rawIndex[0]; + for (int i = 0; i < count; ++i, entryP += 8) { + CCEntry entry; + entry._id = READ_LE_UINT16(entryP); + entry._offset = READ_LE_UINT32(entryP + 2) & 0xffffff; + entry._size = READ_LE_UINT16(entryP + 5); + assert(!entryP[7]); + + _index.push_back(entry); + } + + delete[] rawIndex; +} + +/** +* Given a resource name, returns whether an entry exists, and returns +* the header index data for that entry +*/ +bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const { + uint16 id = convertNameToId(resourceName); + + // Loop through the index + for (uint i = 0; i < _index.size(); ++i) { + if (_index[i]._id == id) { + ccEntry = _index[i]; + return true; + } + } + + // Could not find an entry + return false; +} + +/*------------------------------------------------------------------------*/ + +void FileManager::init(XeenEngine *vm) { + Common::File f; + + if (vm->getGameID() != GType_Clouds) + SearchMan.add("dark", new CCArchive("dark.cc")); + SearchMan.add("xeen", new CCArchive("xeen.cc")); + SearchMan.add("intro", new CCArchive("intro.cc")); +} + +/*------------------------------------------------------------------------*/ + +/** + * Opens the given file, throwing an error if it can't be opened + */ +void File::openFile(const Common::String &filename) { + if (!Common::File::open(filename)) + error("Could not open file - %s", filename.c_str()); +} + +} // End of namespace Xeen diff --git a/engines/xeen/files.h b/engines/xeen/files.h new file mode 100644 index 0000000000..7ef126e01d --- /dev/null +++ b/engines/xeen/files.h @@ -0,0 +1,58 @@ +/* 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 XEEN_FILES_H +#define XEEN_FILES_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/file.h" +#include "graphics/surface.h" +#include "xeen/xsurface.h" + +namespace Xeen { + +class XeenEngine; + +class FileManager { +public: + /** + * Instantiates the resource manager + */ + static void init(XeenEngine *vm); +}; + +/** + * Derived file class + */ +class File : public Common::File { +public: + File() : Common::File() {} + File(const Common::String &filename) { openFile(filename); } + virtual ~File() {} + + void openFile(const Common::String &filename); +}; + +} // End of namespace Xeen + +#endif /* XEEN_FILES_H */ diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp index 8b80ec24ca..b5608d48b8 100644 --- a/engines/xeen/font.cpp +++ b/engines/xeen/font.cpp @@ -22,7 +22,7 @@ #include "common/endian.h" #include "xeen/font.h" -#include "xeen/resdata.h" +#include "xeen/resources.h" namespace Xeen { diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 99eb98174e..cdd8e549d4 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -9,11 +9,13 @@ MODULE_OBJS := \ dialogs.o \ dialogs_options.o \ events.o \ + files.o \ font.o \ resdata.o \ resources.o \ screen.o \ sound.o \ + sprites.o \ xeen.o \ xsurface.o diff --git a/engines/xeen/resdata.cpp b/engines/xeen/resdata.cpp deleted file mode 100644 index b9309b4adb..0000000000 --- a/engines/xeen/resdata.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* 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/scummsys.h" -#include "xeen/resdata.h" - -namespace Xeen { - -const char *const CREDITS = - "\013012\010000\003c\01435Designed and Directed By:\n" - "\01417Jon Van Caneghem\003l\n" - "\n" - "\t025\01435Programming:\n" - "\t035\01417Mark Caldwell\n" - "\t035Dave Hathaway\n" - "\n" - "\t025\01435Sound System & FX:\n" - "\t035\01417Mike Heilemann\n" - "\n" - "\t025\01435Music & Speech:\n" - "\t035\01417Tim Tully\n" - "\n" - "\t025\01435Writing:\n" - "\t035\01417Paul Rattner\n" - "\t035Debbie Van Caneghem\n" - "\t035Jon Van Caneghem\013012\n" - "\n" - "\n" - "\t180\01435Graphics:\n" - "\t190\01417Jonathan P. Gwyn\n" - "\t190Bonita Long-Hemsath\n" - "\t190Julia Ulano\n" - "\t190Ricardo Barrera\n" - "\n" - "\t180\01435Testing:\n" - "\t190\01417Benjamin Bent\n" - "\t190Christian Dailey\n" - "\t190Mario Escamilla\n" - "\t190Marco Hunter\n" - "\t190Robert J. Lupo\n" - "\t190Clayton Retzer\n" - "\t190David Vela\003c"; - -const char *const OPTIONS_TITLE = - "\x0D\x01\003c\014dMight and Magic Options\n" - "World of Xeen\x02\n" - "\v117Copyright (c) 1993 NWC, Inc.\n" - "All Rights Reserved\x01"; - -const byte SYMBOLS[20][64] = { - { // 0 - 0x00, 0x00, 0xA8, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x00, 0xA8, 0x9E, 0x9C, 0x9C, 0x9E, 0x9E, 0x9E, - 0xAC, 0x9C, 0xA4, 0xAC, 0xAC, 0x9A, 0x9A, 0x9A, 0xAC, 0x9E, 0xAC, 0xA8, 0xA8, 0xA6, 0x97, 0x98, - 0xAC, 0xA0, 0xAC, 0xAC, 0xA4, 0xA6, 0x98, 0x99, 0x00, 0xAC, 0xA0, 0xA0, 0xA8, 0xAC, 0x9A, 0x9A, - 0x00, 0x00, 0xAC, 0xAC, 0xAC, 0xA4, 0x9B, 0x9A, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xA0, 0x9B, 0x9B, - }, - { // 1 - 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, - 0x99, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x99, 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x99, 0x98, 0x98, 0x99, 0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, - 0x9A, 0x9B, 0x9B, 0x9C, 0x9B, 0x9A, 0x9C, 0x9A, 0x9B, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x9A, 0x9B, - }, - { // 2 - 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, - 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x99, 0x98, 0x98, 0x99, 0x98, 0x98, 0x97, 0x98, 0x98, - 0x99, 0x98, 0x98, 0x98, 0x99, 0x99, 0x98, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, - 0x9B, 0x9B, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9B, 0x99, 0x9A, 0x9B, 0x9B, 0x9A, 0x9A, 0x99, 0x9A, - }, - { // 3 - 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, - 0x99, 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x98, 0x98, 0x97, 0x97, 0x98, 0x98, 0x98, 0x98, - 0x99, 0x99, 0x98, 0x99, 0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, - 0x9B, 0x9C, 0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0x9C, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x9A, - }, - { // 4 - 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, - 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x99, 0x9A, 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, - 0x99, 0x99, 0x98, 0x99, 0x99, 0x98, 0x98, 0x98, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, - 0x9A, 0x9C, 0x9B, 0x9B, 0x9C, 0x9B, 0x9B, 0x9B, 0x9A, 0x99, 0x9B, 0x9B, 0x9A, 0x99, 0x9A, 0x9A, - }, - { // 5 - 0xA4, 0xA4, 0xA8, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x9E, 0x9E, 0xA0, 0xA8, 0xAC, 0x00, 0x00, - 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9E, 0xAC, 0x00, 0x97, 0x97, 0x97, 0x98, 0x9C, 0x9C, 0xA0, 0xAC, - 0x99, 0x98, 0x99, 0x99, 0x99, 0x9B, 0xA0, 0xAC, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9B, 0xA0, 0xAC, - 0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x9A, 0x9A, 0x9B, 0x9B, 0xA4, 0xAC, 0x00, - }, - { // 6 - 0x00, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x00, 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x9B, 0x99, - 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x98, 0x99, 0x99, - 0x00, 0xAC, 0xA0, 0x9C, 0x9C, 0xA0, 0x9C, 0x9A, 0x00, 0x00, 0xAC, 0xA4, 0xA0, 0x99, 0x99, 0x99, - 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, - }, - { // 7 - 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x9C, 0x99, 0x99, - 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x00, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, - 0x00, 0x00, 0xAC, 0xA0, 0x9B, 0xA0, 0x9E, 0x9C, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x9C, 0x99, 0x99, - }, - { // 8 - 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x9B, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, - 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x9C, 0x99, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x9E, 0x9C, 0x99, - }, - { // 9 - 0x00, 0x00, 0xAC, 0xA4, 0xA0, 0x9C, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x9C, 0xA0, 0x9C, 0x9A, - 0xAC, 0xA4, 0x9C, 0x9A, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, - 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, - 0x00, 0xAC, 0xA4, 0x9C, 0x9A, 0x9C, 0x99, 0x99, 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x9A, 0x99, 0x99, - }, - { // 10 - 0x99, 0x99, 0x99, 0x9A, 0xA0, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00, - 0x99, 0x99, 0x9C, 0x9E, 0xA4, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x9C, 0x99, 0x9C, 0xA4, 0xAC, 0x00, - 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00, - 0x99, 0x99, 0x99, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x9A, 0x9B, 0x9E, 0x9C, 0x9C, 0xA4, 0xAC, 0x00, - }, - { // 11 - 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0x9E, 0xAC, - 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, - 0x9C, 0x99, 0x99, 0x99, 0x9C, 0x9C, 0xA4, 0xAC, 0x99, 0x9E, 0x9E, 0x9C, 0x9C, 0xA0, 0xAC, 0x00, - }, - { // 12 - 0x99, 0x99, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x9B, 0x9C, 0x9E, 0x9C, 0x9C, 0xA4, 0xAC, 0x00, - 0x99, 0x99, 0x99, 0x99, 0x99, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, - 0x99, 0x99, 0x99, 0x99, 0x9C, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, - 0x99, 0x99, 0x9C, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, - }, - { // 13 - 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00, - 0x99, 0x9B, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x9A, 0x99, 0x9C, 0xA0, 0xAC, 0x00, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, - 0x99, 0x99, 0x99, 0x99, 0x9A, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x9A, 0x9C, 0xA4, 0xAC, 0x00, - }, - { // 14 - 0x00, 0x00, 0xAC, 0x9E, 0x9C, 0x9C, 0x9C, 0x9B, 0x00, 0xAC, 0x9C, 0xA0, 0x9E, 0xA4, 0xA4, 0xA4, - 0xAC, 0x9C, 0xA4, 0xAC, 0xAC, 0xAC, 0x9C, 0x9E, 0xAC, 0xA0, 0xAC, 0xA8, 0x9E, 0xA8, 0xAC, 0x99, - 0xAC, 0x9E, 0xAC, 0xA8, 0xAC, 0x9E, 0xA4, 0xAC, 0xAC, 0xA4, 0xA0, 0xAC, 0xAC, 0xA0, 0xA4, 0xAC, - 0x00, 0xAC, 0xA4, 0xA0, 0xA0, 0xA4, 0xAC, 0xA4, 0x00, 0x00, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, - }, - { // 15 - 0x9C, 0x9C, 0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, - 0x9E, 0x9E, 0x9E, 0x9C, 0x9E, 0x9E, 0x9E, 0x9E, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x99, 0x98, - 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x9E, 0x9E, 0xA0, - 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, - }, - { // 16 - 0x9B, 0x9B, 0x9B, 0x9B, 0x9C, 0x9B, 0x9C, 0x9C, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, - 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9E, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99, - 0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0xA0, 0xA0, 0xA0, 0x9E, 0xA0, 0x9E, 0x9E, 0xA0, - 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, - }, - { // 17 - 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9C, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, - 0x9E, 0x9E, 0x9E, 0x9C, 0x9C, 0x9C, 0x9E, 0x9E, 0x98, 0x98, 0x98, 0x99, 0x9A, 0x9A, 0x99, 0x98, - 0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9C, 0xA0, 0x9E, 0x9E, 0xA0, 0xA0, 0xA0, 0xA0, 0x9E, - 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, - }, - { // 18 - 0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, - 0x9E, 0x9E, 0x9E, 0x9E, 0x9C, 0x9C, 0x9C, 0x9E, 0x98, 0x98, 0x98, 0x98, 0x9A, 0x9A, 0x98, 0x99, - 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9B, 0x9C, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0xA0, 0xA0, 0xA0, - 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, - }, - { // 19 - 0x9C, 0x9B, 0x9C, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0x00, 0x00, - 0x9E, 0x9E, 0x9C, 0x9C, 0x9E, 0xA0, 0xAC, 0x00, 0x99, 0x98, 0x98, 0x99, 0x9A, 0x9A, 0xA0, 0xAC, - 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0xA0, 0xAC, 0xA0, 0xA0, 0x9E, 0xA0, 0xA0, 0xA0, 0xA0, 0xAC, - 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0x00, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0x00, 0x00, - } -}; - -const byte TEXT_COLORS[40][4] = { - { 0x00, 0x19, 0x19, 0x19 }, - { 0x00, 0x08, 0x08, 0x08 }, - { 0x00, 0x0F, 0x0F, 0x0F }, - { 0x00, 0x15, 0x15, 0x15 }, - { 0x00, 0x01, 0x01, 0x01 }, - { 0x00, 0x21, 0x21, 0x21 }, - { 0x00, 0x26, 0x26, 0x26 }, - { 0x00, 0x2B, 0x2B, 0x2B }, - { 0x00, 0x31, 0x31, 0x31 }, - { 0x00, 0x36, 0x36, 0x36 }, - { 0x00, 0x3D, 0x3D, 0x3D }, - { 0x00, 0x41, 0x41, 0x41 }, - { 0x00, 0x46, 0x46, 0x46 }, - { 0x00, 0x4C, 0x4C, 0x4C }, - { 0x00, 0x50, 0x50, 0x50 }, - { 0x00, 0x55, 0x55, 0x55 }, - { 0x00, 0x5D, 0x5D, 0x5D }, - { 0x00, 0x60, 0x60, 0x60 }, - { 0x00, 0x65, 0x65, 0x65 }, - { 0x00, 0x6C, 0x6C, 0x6C }, - { 0x00, 0x70, 0x70, 0x70 }, - { 0x00, 0x75, 0x75, 0x75 }, - { 0x00, 0x7B, 0x7B, 0x7B }, - { 0x00, 0x80, 0x80, 0x80 }, - { 0x00, 0x85, 0x85, 0x85 }, - { 0x00, 0x8D, 0x8D, 0x8D }, - { 0x00, 0x90, 0x90, 0x90 }, - { 0x00, 0x97, 0x97, 0x97 }, - { 0x00, 0x9D, 0x9D, 0x9D }, - { 0x00, 0xA4, 0xA4, 0xA4 }, - { 0x00, 0xAB, 0xAB, 0xAB }, - { 0x00, 0xB0, 0xB0, 0xB0 }, - { 0x00, 0xB6, 0xB6, 0xB6 }, - { 0x00, 0xBD, 0xBD, 0xBD }, - { 0x00, 0xC0, 0xC0, 0xC0 }, - { 0x00, 0xC6, 0xC6, 0xC6 }, - { 0x00, 0xCD, 0xCD, 0xCD }, - { 0x00, 0xD0, 0xD0, 0xD0 }, - { 0x00, 0xD6, 0xD6, 0xD6 }, - { 0x00, 0xDB, 0xDB, 0xDB }, -}; - -} // End of namespace Xeen diff --git a/engines/xeen/resdata.h b/engines/xeen/resdata.h deleted file mode 100644 index 3c549fc225..0000000000 --- a/engines/xeen/resdata.h +++ /dev/null @@ -1,41 +0,0 @@ -/* 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 XEEN_RESDATA_H -#define XEEN_RESDATA_H - -#include "common/scummsys.h" -#include "gui/debugger.h" - -namespace Xeen { - -extern const char *const CREDITS; - -extern const char *const OPTIONS_TITLE; - -extern const byte SYMBOLS[20][64]; - -extern const byte TEXT_COLORS[40][4]; - -} // End of namespace Xeen - -#endif /* XEEN_RESDATA_H */ diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index ba2889fc9d..d1177dab00 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -8,12 +8,12 @@ * 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. @@ -21,365 +21,215 @@ */ #include "common/scummsys.h" -#include "common/archive.h" -#include "common/memstream.h" -#include "common/textconsole.h" -#include "xeen/xeen.h" #include "xeen/resources.h" namespace Xeen { -/** - * Xeen CC file implementation - */ -class CCArchive : public Common::Archive { -private: - /** - * Details of a single entry in a CC file index - */ - struct CCEntry { - uint16 _id; - uint32 _offset; - uint16 _size; - - CCEntry() : _id(0), _offset(0), _size(0) {} - CCEntry(uint16 id, uint32 offset, uint32 size) - : _id(id), _offset(offset), _size(size) { - } - }; - - Common::Array<CCEntry> _index; - Common::String _filename; - - uint16 convertNameToId(const Common::String &resourceName) const; - - void loadIndex(Common::SeekableReadStream *stream); - - bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const; -public: - CCArchive(const Common::String &filename); - virtual ~CCArchive(); - - // Archive implementation - virtual bool hasFile(const Common::String &name) const; - virtual int listMembers(Common::ArchiveMemberList &list) const; - virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const; - virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; -}; - -CCArchive::CCArchive(const Common::String &filename): _filename(filename) { - File f(filename); - loadIndex(&f); -} - -CCArchive::~CCArchive() { -} - -// Archive implementation -bool CCArchive::hasFile(const Common::String &name) const { - CCEntry ccEntry; - return getHeaderEntry(name, ccEntry); -} - -int CCArchive::listMembers(Common::ArchiveMemberList &list) const { - // CC files don't maintain the original filenames, so we can't list it - return 0; -} - -const Common::ArchiveMemberPtr CCArchive::getMember(const Common::String &name) const { - if (!hasFile(name)) - return Common::ArchiveMemberPtr(); - - return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this)); -} - -Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::String &name) const { - CCEntry ccEntry; - - if (getHeaderEntry(name, ccEntry)) { - // Open the correct CC file - Common::File f; - if (!f.open(_filename)) - error("Could not open CC file"); - - // Read in the data for the specific resource - f.seek(ccEntry._offset); - byte *data = new byte[ccEntry._size]; - f.read(data, ccEntry._size); - - // Decrypt the data - for (int i = 0; i < ccEntry._size; ++i) - data[i] ^= 0x35; - - // Return the data as a stream - return new Common::MemoryReadStream(data, ccEntry._size, DisposeAfterUse::YES); - } - - return nullptr; -} - -/** - * Hash a given filename to produce the Id that represents it - */ -uint16 CCArchive::convertNameToId(const Common::String &resourceName) const { - if (resourceName.empty()) - return 0xffff; - - Common::String name = resourceName; - name.toUppercase(); - - const byte *msgP = (const byte *)name.c_str(); - int total = *msgP++; - for (; *msgP; total += *msgP++) { - // Rotate the bits in 'total' right 7 places - total = (total & 0x007F) << 9 | (total & 0xFF80) >> 7; - } - - return total; -} - -/** - * Load the index of a given CC file - */ -void CCArchive::loadIndex(Common::SeekableReadStream *stream) { - int count = stream->readUint16LE(); - - // Read in the data for the archive's index - byte *rawIndex = new byte[count * 8]; - stream->read(rawIndex, count * 8); - - // Decrypt the index - int ah = 0xac; - for (int i = 0; i < count * 8; ++i) { - rawIndex[i] = (byte)(((rawIndex[i] << 2 | rawIndex[i] >> 6) + ah) & 0xff); - ah += 0x67; - } - - // Extract the index data into entry structures - _index.reserve(count); - const byte *entryP = &rawIndex[0]; - for (int i = 0; i < count; ++i, entryP += 8) { - CCEntry entry; - entry._id = READ_LE_UINT16(entryP); - entry._offset = READ_LE_UINT32(entryP + 2) & 0xffffff; - entry._size = READ_LE_UINT16(entryP + 5); - assert(!entryP[7]); - - _index.push_back(entry); - } - - delete[] rawIndex; -} - -/** -* Given a resource name, returns whether an entry exists, and returns -* the header index data for that entry -*/ -bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const { - uint16 id = convertNameToId(resourceName); - - // Loop through the index - for (uint i = 0; i < _index.size(); ++i) { - if (_index[i]._id == id) { - ccEntry = _index[i]; - return true; - } - } - - // Could not find an entry - return false; -} - -/*------------------------------------------------------------------------*/ - -void Resources::init(XeenEngine *vm) { - Common::File f; - - if (vm->getGameID() != GType_Clouds) - SearchMan.add("dark", new CCArchive("dark.cc")); - SearchMan.add("xeen", new CCArchive("xeen.cc")); - SearchMan.add("intro", new CCArchive("intro.cc")); -} - -/*------------------------------------------------------------------------*/ - -/** - * Opens the given file, throwing an error if it can't be opened - */ -void File::openFile(const Common::String &filename) { - if (!Common::File::open(filename)) - error("Could not open file - %s", filename.c_str()); -} - -/*------------------------------------------------------------------------*/ - -GraphicResource::GraphicResource(const Common::String &filename) { - // Open the resource - File f(filename); - - // Read in a copy of the file - _filesize = f.size(); - _data = new byte[_filesize]; - f.seek(0); - f.read(_data, _filesize); -} - -GraphicResource::~GraphicResource() { - delete[] _data; -} - -int GraphicResource::size() const { - return READ_LE_UINT16(_data); -} - -void GraphicResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const { - // Get cell header - Common::MemoryReadStream f(_data, _filesize); - f.seek(offset); - int xOffset = f.readUint16LE(); - int width = f.readUint16LE(); - int yOffset = f.readUint16LE(); - int height = f.readUint16LE(); - - if (dest.w < (xOffset + width) || dest.h < (yOffset + height)) - dest.create(xOffset + width, yOffset + height); - - // The pattern steps used in the pattern command - const int patternSteps[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 }; - - // Main loop - int opr1, opr2; - int32 pos; - for (int yPos = yOffset, byteCount = 0; yPos < height + yOffset; yPos++, byteCount = 0) { - // The number of bytes in this scan line - int lineLength = f.readByte(); - - if (lineLength == 0) { - // Skip the specified number of scan lines - yPos += f.readByte(); - } else { - // Skip the transparent pixels at the beginning of the scan line - int xPos = f.readByte() + xOffset; ++byteCount; - byte *destP = (byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos); - - while (byteCount < lineLength) { - // The next byte is an opcode that determines what - // operators are to follow and how to interpret them. - int opcode = f.readByte(); ++byteCount; - - // Decode the opcode - int len = opcode & 0x1F; - int cmd = (opcode & 0xE0) >> 5; - - switch (cmd) { - case 0: // The following len + 1 bytes are stored as indexes into the color table. - case 1: // The following len + 33 bytes are stored as indexes into the color table. - for (int i = 0; i < opcode + 1; ++i, ++xPos) { - *destP++ = f.readByte(); ++byteCount; - } - break; - - case 2: // The following byte is an index into the color table, draw it len + 3 times. - opr1 = f.readByte(); ++byteCount; - for (int i = 0; i < len + 3; ++i, ++xPos) - *destP++ = opr1; - break; - - case 3: // Stream copy command. - opr1 = f.readUint16LE(); byteCount += 2; - pos = f.pos(); - f.seek(-opr1, SEEK_CUR); - - for (int i = 0; i < len + 4; ++i, ++xPos) - *destP++ = f.readByte(); - - f.seek(pos, SEEK_SET); - break; - - case 4: // The following two bytes are indexes into the color table, draw the pair len + 2 times. - opr1 = f.readByte(); ++byteCount; - opr2 = f.readByte(); ++byteCount; - for (int i = 0; i < len + 2; ++i, xPos += 2) { - *destP++ = opr1; - *destP++ = opr2; - } - break; - - case 5: // Skip len + 1 pixels filling them with the transparent color. - xPos += len + 1; - destP += len + 1; - break; - - case 6: // Pattern command. - case 7: - // The pattern command has a different opcode format - len = opcode & 0x07; - cmd = (opcode >> 2) & 0x0E; - - opr1 = f.readByte(); ++byteCount; - for (int i = 0; i < len + 3; ++i, ++xPos) { - *destP++ = opr1; - opr1 += patternSteps[cmd + (i % 2)]; - } - break; - default: - break; - } - } - - assert(byteCount == lineLength); - } +const char *const CREDITS = + "\013012\010000\003c\01435Designed and Directed By:\n" + "\01417Jon Van Caneghem\003l\n" + "\n" + "\t025\01435Programming:\n" + "\t035\01417Mark Caldwell\n" + "\t035Dave Hathaway\n" + "\n" + "\t025\01435Sound System & FX:\n" + "\t035\01417Mike Heilemann\n" + "\n" + "\t025\01435Music & Speech:\n" + "\t035\01417Tim Tully\n" + "\n" + "\t025\01435Writing:\n" + "\t035\01417Paul Rattner\n" + "\t035Debbie Van Caneghem\n" + "\t035Jon Van Caneghem\013012\n" + "\n" + "\n" + "\t180\01435Graphics:\n" + "\t190\01417Jonathan P. Gwyn\n" + "\t190Bonita Long-Hemsath\n" + "\t190Julia Ulano\n" + "\t190Ricardo Barrera\n" + "\n" + "\t180\01435Testing:\n" + "\t190\01417Benjamin Bent\n" + "\t190Christian Dailey\n" + "\t190Mario Escamilla\n" + "\t190Marco Hunter\n" + "\t190Robert J. Lupo\n" + "\t190Clayton Retzer\n" + "\t190David Vela\003c"; + +const char *const OPTIONS_TITLE = + "\x0D\x01\003c\014dMight and Magic Options\n" + "World of Xeen\x02\n" + "\v117Copyright (c) 1993 NWC, Inc.\n" + "All Rights Reserved\x01"; + +const byte SYMBOLS[20][64] = { + { // 0 + 0x00, 0x00, 0xA8, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x00, 0xA8, 0x9E, 0x9C, 0x9C, 0x9E, 0x9E, 0x9E, + 0xAC, 0x9C, 0xA4, 0xAC, 0xAC, 0x9A, 0x9A, 0x9A, 0xAC, 0x9E, 0xAC, 0xA8, 0xA8, 0xA6, 0x97, 0x98, + 0xAC, 0xA0, 0xAC, 0xAC, 0xA4, 0xA6, 0x98, 0x99, 0x00, 0xAC, 0xA0, 0xA0, 0xA8, 0xAC, 0x9A, 0x9A, + 0x00, 0x00, 0xAC, 0xAC, 0xAC, 0xA4, 0x9B, 0x9A, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xA0, 0x9B, 0x9B, + }, + { // 1 + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, + 0x99, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x99, 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x99, 0x98, 0x98, 0x99, 0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, + 0x9A, 0x9B, 0x9B, 0x9C, 0x9B, 0x9A, 0x9C, 0x9A, 0x9B, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x9A, 0x9B, + }, + { // 2 + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, + 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x99, 0x98, 0x98, 0x99, 0x98, 0x98, 0x97, 0x98, 0x98, + 0x99, 0x98, 0x98, 0x98, 0x99, 0x99, 0x98, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, + 0x9B, 0x9B, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9B, 0x99, 0x9A, 0x9B, 0x9B, 0x9A, 0x9A, 0x99, 0x9A, + }, + { // 3 + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, + 0x99, 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x98, 0x98, 0x97, 0x97, 0x98, 0x98, 0x98, 0x98, + 0x99, 0x99, 0x98, 0x99, 0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, + 0x9B, 0x9C, 0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0x9C, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x9A, + }, + { // 4 + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, + 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x99, 0x9A, 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, + 0x99, 0x99, 0x98, 0x99, 0x99, 0x98, 0x98, 0x98, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, + 0x9A, 0x9C, 0x9B, 0x9B, 0x9C, 0x9B, 0x9B, 0x9B, 0x9A, 0x99, 0x9B, 0x9B, 0x9A, 0x99, 0x9A, 0x9A, + }, + { // 5 + 0xA4, 0xA4, 0xA8, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x9E, 0x9E, 0xA0, 0xA8, 0xAC, 0x00, 0x00, + 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9E, 0xAC, 0x00, 0x97, 0x97, 0x97, 0x98, 0x9C, 0x9C, 0xA0, 0xAC, + 0x99, 0x98, 0x99, 0x99, 0x99, 0x9B, 0xA0, 0xAC, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9B, 0xA0, 0xAC, + 0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x9A, 0x9A, 0x9B, 0x9B, 0xA4, 0xAC, 0x00, + }, + { // 6 + 0x00, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x00, 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x9B, 0x99, + 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x98, 0x99, 0x99, + 0x00, 0xAC, 0xA0, 0x9C, 0x9C, 0xA0, 0x9C, 0x9A, 0x00, 0x00, 0xAC, 0xA4, 0xA0, 0x99, 0x99, 0x99, + 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, + }, + { // 7 + 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x9C, 0x99, 0x99, + 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x00, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, + 0x00, 0x00, 0xAC, 0xA0, 0x9B, 0xA0, 0x9E, 0x9C, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x9C, 0x99, 0x99, + }, + { // 8 + 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x9B, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, + 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x9C, 0x99, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x9E, 0x9C, 0x99, + }, + { // 9 + 0x00, 0x00, 0xAC, 0xA4, 0xA0, 0x9C, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x9C, 0xA0, 0x9C, 0x9A, + 0xAC, 0xA4, 0x9C, 0x9A, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, + 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, + 0x00, 0xAC, 0xA4, 0x9C, 0x9A, 0x9C, 0x99, 0x99, 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x9A, 0x99, 0x99, + }, + { // 10 + 0x99, 0x99, 0x99, 0x9A, 0xA0, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00, + 0x99, 0x99, 0x9C, 0x9E, 0xA4, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x9C, 0x99, 0x9C, 0xA4, 0xAC, 0x00, + 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00, + 0x99, 0x99, 0x99, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x9A, 0x9B, 0x9E, 0x9C, 0x9C, 0xA4, 0xAC, 0x00, + }, + { // 11 + 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0x9E, 0xAC, + 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, + 0x9C, 0x99, 0x99, 0x99, 0x9C, 0x9C, 0xA4, 0xAC, 0x99, 0x9E, 0x9E, 0x9C, 0x9C, 0xA0, 0xAC, 0x00, + }, + { // 12 + 0x99, 0x99, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x9B, 0x9C, 0x9E, 0x9C, 0x9C, 0xA4, 0xAC, 0x00, + 0x99, 0x99, 0x99, 0x99, 0x99, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, + 0x99, 0x99, 0x99, 0x99, 0x9C, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, + 0x99, 0x99, 0x9C, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, + }, + { // 13 + 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00, + 0x99, 0x9B, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x9A, 0x99, 0x9C, 0xA0, 0xAC, 0x00, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x9A, 0x9C, 0xA4, 0xAC, 0x00, + }, + { // 14 + 0x00, 0x00, 0xAC, 0x9E, 0x9C, 0x9C, 0x9C, 0x9B, 0x00, 0xAC, 0x9C, 0xA0, 0x9E, 0xA4, 0xA4, 0xA4, + 0xAC, 0x9C, 0xA4, 0xAC, 0xAC, 0xAC, 0x9C, 0x9E, 0xAC, 0xA0, 0xAC, 0xA8, 0x9E, 0xA8, 0xAC, 0x99, + 0xAC, 0x9E, 0xAC, 0xA8, 0xAC, 0x9E, 0xA4, 0xAC, 0xAC, 0xA4, 0xA0, 0xAC, 0xAC, 0xA0, 0xA4, 0xAC, + 0x00, 0xAC, 0xA4, 0xA0, 0xA0, 0xA4, 0xAC, 0xA4, 0x00, 0x00, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, + }, + { // 15 + 0x9C, 0x9C, 0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, + 0x9E, 0x9E, 0x9E, 0x9C, 0x9E, 0x9E, 0x9E, 0x9E, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x99, 0x98, + 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x9E, 0x9E, 0xA0, + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, + }, + { // 16 + 0x9B, 0x9B, 0x9B, 0x9B, 0x9C, 0x9B, 0x9C, 0x9C, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, + 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9E, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99, + 0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0xA0, 0xA0, 0xA0, 0x9E, 0xA0, 0x9E, 0x9E, 0xA0, + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, + }, + { // 17 + 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9C, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, + 0x9E, 0x9E, 0x9E, 0x9C, 0x9C, 0x9C, 0x9E, 0x9E, 0x98, 0x98, 0x98, 0x99, 0x9A, 0x9A, 0x99, 0x98, + 0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9C, 0xA0, 0x9E, 0x9E, 0xA0, 0xA0, 0xA0, 0xA0, 0x9E, + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, + }, + { // 18 + 0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, + 0x9E, 0x9E, 0x9E, 0x9E, 0x9C, 0x9C, 0x9C, 0x9E, 0x98, 0x98, 0x98, 0x98, 0x9A, 0x9A, 0x98, 0x99, + 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9B, 0x9C, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0xA0, 0xA0, 0xA0, + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, + }, + { // 19 + 0x9C, 0x9B, 0x9C, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0x00, 0x00, + 0x9E, 0x9E, 0x9C, 0x9C, 0x9E, 0xA0, 0xAC, 0x00, 0x99, 0x98, 0x98, 0x99, 0x9A, 0x9A, 0xA0, 0xAC, + 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0xA0, 0xAC, 0xA0, 0xA0, 0x9E, 0xA0, 0xA0, 0xA0, 0xA0, 0xAC, + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0x00, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0x00, 0x00, } +}; - dest.addDirtyRect(Common::Rect(destPos.x + xOffset, destPos.y + yOffset, - destPos.x + xOffset + width, destPos.y + yOffset + height)); -} - -/*------------------------------------------------------------------------*/ - -FramesResource::FramesResource(const Common::String &filename) : - GraphicResource(filename) { - // Read in the index - Common::MemoryReadStream f(_data, _filesize); - int count = f.readUint16LE(); - _index.resize(count); - - for (int i = 0; i < count; ++i) { - _index[i] = f.readUint32LE(); - } -} - -void FramesResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const { - drawOffset(dest, _index[frame], destPos); -} - -void FramesResource::draw(XSurface &dest, int frame) const { - draw(dest, frame, Common::Point()); -} - -/*------------------------------------------------------------------------*/ - -SpriteResource::SpriteResource(const Common::String &filename) : - GraphicResource(filename) { - // Read in the index - Common::MemoryReadStream f(_data, _filesize); - int count = f.readUint16LE(); - _index.resize(count); - - for (int i = 0; i < count; ++i) { - _index[i]._offset1 = f.readUint16LE(); - _index[i]._offset2 = f.readUint16LE(); - } -} - -void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const { - drawOffset(dest, _index[frame]._offset1, destPos); - if (_index[frame]._offset2) - drawOffset(dest, _index[frame]._offset2, destPos); -} - -void SpriteResource::draw(XSurface &dest, int frame) const { - draw(dest, frame, Common::Point()); -} +const byte TEXT_COLORS[40][4] = { + { 0x00, 0x19, 0x19, 0x19 }, + { 0x00, 0x08, 0x08, 0x08 }, + { 0x00, 0x0F, 0x0F, 0x0F }, + { 0x00, 0x15, 0x15, 0x15 }, + { 0x00, 0x01, 0x01, 0x01 }, + { 0x00, 0x21, 0x21, 0x21 }, + { 0x00, 0x26, 0x26, 0x26 }, + { 0x00, 0x2B, 0x2B, 0x2B }, + { 0x00, 0x31, 0x31, 0x31 }, + { 0x00, 0x36, 0x36, 0x36 }, + { 0x00, 0x3D, 0x3D, 0x3D }, + { 0x00, 0x41, 0x41, 0x41 }, + { 0x00, 0x46, 0x46, 0x46 }, + { 0x00, 0x4C, 0x4C, 0x4C }, + { 0x00, 0x50, 0x50, 0x50 }, + { 0x00, 0x55, 0x55, 0x55 }, + { 0x00, 0x5D, 0x5D, 0x5D }, + { 0x00, 0x60, 0x60, 0x60 }, + { 0x00, 0x65, 0x65, 0x65 }, + { 0x00, 0x6C, 0x6C, 0x6C }, + { 0x00, 0x70, 0x70, 0x70 }, + { 0x00, 0x75, 0x75, 0x75 }, + { 0x00, 0x7B, 0x7B, 0x7B }, + { 0x00, 0x80, 0x80, 0x80 }, + { 0x00, 0x85, 0x85, 0x85 }, + { 0x00, 0x8D, 0x8D, 0x8D }, + { 0x00, 0x90, 0x90, 0x90 }, + { 0x00, 0x97, 0x97, 0x97 }, + { 0x00, 0x9D, 0x9D, 0x9D }, + { 0x00, 0xA4, 0xA4, 0xA4 }, + { 0x00, 0xAB, 0xAB, 0xAB }, + { 0x00, 0xB0, 0xB0, 0xB0 }, + { 0x00, 0xB6, 0xB6, 0xB6 }, + { 0x00, 0xBD, 0xBD, 0xBD }, + { 0x00, 0xC0, 0xC0, 0xC0 }, + { 0x00, 0xC6, 0xC6, 0xC6 }, + { 0x00, 0xCD, 0xCD, 0xCD }, + { 0x00, 0xD0, 0xD0, 0xD0 }, + { 0x00, 0xD6, 0xD6, 0xD6 }, + { 0x00, 0xDB, 0xDB, 0xDB }, +}; } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 0476319875..d24b1fe4bf 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -8,12 +8,12 @@ * 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. @@ -24,84 +24,18 @@ #define XEEN_RESOURCES_H #include "common/scummsys.h" -#include "common/array.h" -#include "common/file.h" -#include "graphics/surface.h" -#include "xeen/xsurface.h" +#include "gui/debugger.h" namespace Xeen { -class XeenEngine; - -class Resources { -public: - /** - * Instantiates the resource manager - */ - static void init(XeenEngine *vm); -}; - -/** - * Derived file class - */ -class File : public Common::File { -public: - File() : Common::File() {} - File(const Common::String &filename) { openFile(filename); } - virtual ~File() {} - - void openFile(const Common::String &filename); -}; - -class GraphicResource { -protected: - int32 _filesize; - byte *_data; - - void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const; -public: - GraphicResource(const Common::String &filename); - - virtual ~GraphicResource(); - - int size() const; -}; - -/** - * Defines a resource that Contains a list of singular sprite frames - */ -class FramesResource : public GraphicResource { -private: - Common::Array<uint32> _index; -public: - FramesResource(const Common::String &filename); - virtual ~FramesResource() {} - - void draw(XSurface &dest, int frame, const Common::Point &destPos) const; - - void draw(XSurface &dest, int frame) const; -}; - -/** - * Defines a resource that contains sets of two layered sprites per frame - */ -class SpriteResource : public GraphicResource { -private: - struct IndexEntry { - uint16 _offset1, _offset2; - }; - Common::Array<IndexEntry> _index; - -public: - SpriteResource(const Common::String &filename); +extern const char *const CREDITS; - virtual ~SpriteResource() {} +extern const char *const OPTIONS_TITLE; - void draw(XSurface &dest, int frame, const Common::Point &destPos) const; +extern const byte SYMBOLS[20][64]; - void draw(XSurface &dest, int frame) const; -}; +extern const byte TEXT_COLORS[40][4]; } // End of namespace Xeen -#endif /* MADS_RESOURCES_H */ +#endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index 73f5aa0633..f375b985f8 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -25,7 +25,7 @@ #include "common/scummsys.h" #include "common/system.h" -#include "xeen/resources.h" +#include "xeen/files.h" namespace Xeen { diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp new file mode 100644 index 0000000000..1b18e98dfd --- /dev/null +++ b/engines/xeen/sprites.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 "common/scummsys.h" +#include "common/archive.h" +#include "common/memstream.h" +#include "common/textconsole.h" +#include "xeen/xeen.h" +#include "xeen/sprites.h" + +namespace Xeen { + +GraphicResource::GraphicResource(const Common::String &filename) { + // Open the resource + File f(filename); + + // Read in a copy of the file + _filesize = f.size(); + _data = new byte[_filesize]; + f.seek(0); + f.read(_data, _filesize); +} + +GraphicResource::~GraphicResource() { + delete[] _data; +} + +int GraphicResource::size() const { + return READ_LE_UINT16(_data); +} + +void GraphicResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const { + // Get cell header + Common::MemoryReadStream f(_data, _filesize); + f.seek(offset); + int xOffset = f.readUint16LE(); + int width = f.readUint16LE(); + int yOffset = f.readUint16LE(); + int height = f.readUint16LE(); + + if (dest.w < (xOffset + width) || dest.h < (yOffset + height)) + dest.create(xOffset + width, yOffset + height); + + // The pattern steps used in the pattern command + const int patternSteps[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 }; + + // Main loop + int opr1, opr2; + int32 pos; + for (int yPos = yOffset, byteCount = 0; yPos < height + yOffset; yPos++, byteCount = 0) { + // The number of bytes in this scan line + int lineLength = f.readByte(); + + if (lineLength == 0) { + // Skip the specified number of scan lines + yPos += f.readByte(); + } else { + // Skip the transparent pixels at the beginning of the scan line + int xPos = f.readByte() + xOffset; ++byteCount; + byte *destP = (byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos); + + while (byteCount < lineLength) { + // The next byte is an opcode that determines what + // operators are to follow and how to interpret them. + int opcode = f.readByte(); ++byteCount; + + // Decode the opcode + int len = opcode & 0x1F; + int cmd = (opcode & 0xE0) >> 5; + + switch (cmd) { + case 0: // The following len + 1 bytes are stored as indexes into the color table. + case 1: // The following len + 33 bytes are stored as indexes into the color table. + for (int i = 0; i < opcode + 1; ++i, ++xPos) { + *destP++ = f.readByte(); ++byteCount; + } + break; + + case 2: // The following byte is an index into the color table, draw it len + 3 times. + opr1 = f.readByte(); ++byteCount; + for (int i = 0; i < len + 3; ++i, ++xPos) + *destP++ = opr1; + break; + + case 3: // Stream copy command. + opr1 = f.readUint16LE(); byteCount += 2; + pos = f.pos(); + f.seek(-opr1, SEEK_CUR); + + for (int i = 0; i < len + 4; ++i, ++xPos) + *destP++ = f.readByte(); + + f.seek(pos, SEEK_SET); + break; + + case 4: // The following two bytes are indexes into the color table, draw the pair len + 2 times. + opr1 = f.readByte(); ++byteCount; + opr2 = f.readByte(); ++byteCount; + for (int i = 0; i < len + 2; ++i, xPos += 2) { + *destP++ = opr1; + *destP++ = opr2; + } + break; + + case 5: // Skip len + 1 pixels filling them with the transparent color. + xPos += len + 1; + destP += len + 1; + break; + + case 6: // Pattern command. + case 7: + // The pattern command has a different opcode format + len = opcode & 0x07; + cmd = (opcode >> 2) & 0x0E; + + opr1 = f.readByte(); ++byteCount; + for (int i = 0; i < len + 3; ++i, ++xPos) { + *destP++ = opr1; + opr1 += patternSteps[cmd + (i % 2)]; + } + break; + default: + break; + } + } + + assert(byteCount == lineLength); + } + } + + dest.addDirtyRect(Common::Rect(destPos.x + xOffset, destPos.y + yOffset, + destPos.x + xOffset + width, destPos.y + yOffset + height)); +} + +/*------------------------------------------------------------------------*/ + +FramesResource::FramesResource(const Common::String &filename) : + GraphicResource(filename) { + // Read in the index + Common::MemoryReadStream f(_data, _filesize); + int count = f.readUint16LE(); + _index.resize(count); + + for (int i = 0; i < count; ++i) { + _index[i] = f.readUint32LE(); + } +} + +void FramesResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const { + drawOffset(dest, _index[frame], destPos); +} + +void FramesResource::draw(XSurface &dest, int frame) const { + draw(dest, frame, Common::Point()); +} + +/*------------------------------------------------------------------------*/ + +SpriteResource::SpriteResource(const Common::String &filename) : + GraphicResource(filename) { + // Read in the index + Common::MemoryReadStream f(_data, _filesize); + int count = f.readUint16LE(); + _index.resize(count); + + for (int i = 0; i < count; ++i) { + _index[i]._offset1 = f.readUint16LE(); + _index[i]._offset2 = f.readUint16LE(); + } +} + +void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const { + drawOffset(dest, _index[frame]._offset1, destPos); + if (_index[frame]._offset2) + drawOffset(dest, _index[frame]._offset2, destPos); +} + +void SpriteResource::draw(XSurface &dest, int frame) const { + draw(dest, frame, Common::Point()); +} + +} // End of namespace Xeen diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h new file mode 100644 index 0000000000..6c01a9ff82 --- /dev/null +++ b/engines/xeen/sprites.h @@ -0,0 +1,87 @@ +/* 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 XEEN_SPRITES_H +#define XEEN_SPRITES_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/file.h" +#include "graphics/surface.h" +#include "xeen/xsurface.h" + +namespace Xeen { + +class XeenEngine; + +class GraphicResource { +protected: + int32 _filesize; + byte *_data; + + void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const; +public: + GraphicResource(const Common::String &filename); + + virtual ~GraphicResource(); + + int size() const; +}; + +/** + * Defines a resource that Contains a list of singular sprite frames + */ +class FramesResource : public GraphicResource { +private: + Common::Array<uint32> _index; +public: + FramesResource(const Common::String &filename); + virtual ~FramesResource() {} + + void draw(XSurface &dest, int frame, const Common::Point &destPos) const; + + void draw(XSurface &dest, int frame) const; +}; + +/** + * Defines a resource that contains sets of two layered sprites per frame + */ +class SpriteResource : public GraphicResource { +private: + struct IndexEntry { + uint16 _offset1, _offset2; + }; + Common::Array<IndexEntry> _index; + +public: + SpriteResource(const Common::String &filename); + + virtual ~SpriteResource() {} + + void draw(XSurface &dest, int frame, const Common::Point &destPos) const; + + void draw(XSurface &dest, int frame) const; +}; + +} // End of namespace Xeen + +#endif /* MADS_SPRITES_H */ diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index cbdb6f3104..b61d6a6cc2 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -29,7 +29,7 @@ #include "graphics/thumbnail.h" #include "xeen/xeen.h" #include "xeen/dialogs_options.h" -#include "xeen/resources.h" +#include "xeen/files.h" namespace Xeen { @@ -58,7 +58,7 @@ void XeenEngine::initialize() { DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling"); // Create sub-objects of the engine - Resources::init(this); + FileManager::init(this); _debugger = new Debugger(this); _events = new EventsManager(this); _screen = new Screen(this); diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp index dc42a6fb24..698e478aee 100644 --- a/engines/xeen/xsurface.cpp +++ b/engines/xeen/xsurface.cpp @@ -23,7 +23,7 @@ #include "common/algorithm.h" #include "common/util.h" #include "xeen/xsurface.h" -#include "xeen/resdata.h" +#include "xeen/resources.h" namespace Xeen { -- cgit v1.2.3 From 971a70a2b3cea2ab6d0d77b130c8300ad5f05ca7 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 1 Jan 2015 19:15:08 -1000 Subject: XEEN: Implemented party and condition classes --- engines/xeen/items.cpp | 39 +++++++ engines/xeen/items.h | 45 ++++++++ engines/xeen/module.mk | 2 + engines/xeen/saves.cpp | 292 +++++++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/saves.h | 190 ++++++++++++++++++++++++++++++++ engines/xeen/xeen.cpp | 23 +++- engines/xeen/xeen.h | 6 + 7 files changed, 596 insertions(+), 1 deletion(-) create mode 100644 engines/xeen/items.cpp create mode 100644 engines/xeen/items.h create mode 100644 engines/xeen/saves.cpp create mode 100644 engines/xeen/saves.h (limited to 'engines/xeen') diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp new file mode 100644 index 0000000000..e22e8656d7 --- /dev/null +++ b/engines/xeen/items.cpp @@ -0,0 +1,39 @@ +/* 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 "xeen/items.h" + +namespace Xeen { + +XeenItem::XeenItem() { + _material = _name = _bonusFlags = 0; + _equipped = false; +} + +void XeenItem::synchronize(Common::Serializer &s) { + s.syncAsByte(_material); + s.syncAsByte(_name); + s.syncAsByte(_bonusFlags); + s.syncAsByte(_equipped); +} + +} // End of namespace Xeen diff --git a/engines/xeen/items.h b/engines/xeen/items.h new file mode 100644 index 0000000000..eba2354da5 --- /dev/null +++ b/engines/xeen/items.h @@ -0,0 +1,45 @@ +/* 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 XEEN_ITEMS_H +#define XEEN_ITEMS_H + +#include "common/scummsys.h" +#include "common/serializer.h" + +namespace Xeen { + +class XeenItem { +public: + int _material; + int _name; + int _bonusFlags; + bool _equipped; +public: + XeenItem(); + + void synchronize(Common::Serializer &s); +}; + +} // End of namespace Xeen + +#endif /* XEEN_ITEMS_H */ diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index cdd8e549d4..2f5a092ca9 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -11,8 +11,10 @@ MODULE_OBJS := \ events.o \ files.o \ font.o \ + items.o \ resdata.o \ resources.o \ + saves.o \ screen.o \ sound.o \ sprites.o \ diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp new file mode 100644 index 0000000000..af74b58037 --- /dev/null +++ b/engines/xeen/saves.cpp @@ -0,0 +1,292 @@ +/* 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/scummsys.h" +#include "common/algorithm.h" +#include "xeen/saves.h" + +namespace Xeen { + +AttributePair::AttributePair() { + _temporary = _permanent = 0; +} + +void AttributePair::synchronize(Common::Serializer &s) { + s.syncAsByte(_permanent); + s.syncAsByte(_temporary); +} + +/*------------------------------------------------------------------------*/ + +Roster::Roster() { + _partyCount = 0; + _realPartyCount = 0; + Common::fill(&_partyMembers[0], &_partyMembers[8], 0); + _mazeDirection = DIR_NORTH; + _mazeId = _priorMazeId = 0; + _levitateActive = false; + _automapOn = false; + _wizardEyeActive = false; + _clairvoyanceActive = false; + _walkOnWaterActive = false; + _blessedActive = false; + _powerShieldActive = false; + _holyBonusActive = false; + _heroismActive = false; + _difficulty = ADVENTURER; + _cloudsEnd = false; + _darkSideEnd = false; + _worldEnd = false; + hour_maybe = 0; + _day = 0; + _year = 0; + _minutes = 0; + _food = 0; + _lightCount = 0; + _torchCount = 0; + _fireResistence = 0; + _electricityResistence = 0; + _coldResistence = 0; + _poisonResistence = 0; + _deathCount = 0; + _winCount = 0; + _lossCount = 0; + _gold = 0; + _gems = 0; + _bankGold = 0; + _bankGems = 0; + _totalTime = 0; + _rested = false; + Common::fill(&_gameFlags[0], &_gameFlags[256], false); + Common::fill(&_autoNotes[0], &_autoNotes[128], false); + Common::fill(&_quests[0], &_quests[64], false); + Common::fill(&_questItems[0], &_questItems[65], 0); + Common::fill(&_characterFlags[0][0], &_characterFlags[30][24], false); +} + +void Roster::synchronize(Common::Serializer &s) { + byte dummy[30]; + Common::fill(&dummy[0], &dummy[30], 0); + + s.syncAsByte(_partyCount); + s.syncAsByte(_realPartyCount); + for (int i = 0; i < 8; ++i) + s.syncAsByte(_partyMembers[i]); + s.syncAsByte(_mazeDirection); + s.syncAsByte(_mazePosition.x); + s.syncAsByte(_mazePosition.y); + s.syncAsByte(_mazeId); + + // Game configuration flags not used in this implementation + s.syncBytes(dummy, 3); + + s.syncAsByte(_priorMazeId); + s.syncAsByte(_levitateActive); + s.syncAsByte(_automapOn); + s.syncAsByte(_wizardEyeActive); + s.syncAsByte(_clairvoyanceActive); + s.syncAsByte(_walkOnWaterActive); + s.syncAsByte(_blessedActive); + s.syncAsByte(_powerShieldActive); + s.syncAsByte(_holyBonusActive); + s.syncAsByte(_heroismActive); + s.syncAsByte(_difficulty); + + for (int i = 0; ITEMS_COUNT; ++i) + _blacksmithWeapons[i].synchronize(s); + for (int i = 0; ITEMS_COUNT; ++i) + _blacksmithArmor[i].synchronize(s); + for (int i = 0; ITEMS_COUNT; ++i) + _blacksmithAccessories[i].synchronize(s); + for (int i = 0; ITEMS_COUNT; ++i) + _blacksmithMisc[i].synchronize(s); + + s.syncAsUint16LE(_cloudsEnd); + s.syncAsUint16LE(_darkSideEnd); + s.syncAsUint16LE(_worldEnd); + s.syncAsUint16LE(hour_maybe); + s.syncAsUint16LE(_day); + s.syncAsUint16LE(_year); + s.syncAsUint16LE(_minutes); + s.syncAsUint16LE(_food); + s.syncAsUint16LE(_lightCount); + s.syncAsUint16LE(_torchCount); + s.syncAsUint16LE(_fireResistence); + s.syncAsUint16LE(_electricityResistence); + s.syncAsUint16LE(_coldResistence); + s.syncAsUint16LE(_poisonResistence); + s.syncAsUint16LE(_deathCount); + s.syncAsUint16LE(_winCount); + s.syncAsUint16LE(_lossCount); + s.syncAsUint32LE(_gold); + s.syncAsUint32LE(_gems); + s.syncAsUint32LE(_bankGold); + s.syncAsUint32LE(_bankGems); + s.syncAsUint32LE(_totalTime); + s.syncAsByte(_rested); + SavesManager::syncBitFlags(s, &_gameFlags[0], &_gameFlags[512]); + SavesManager::syncBitFlags(s, &_autoNotes[0], &_autoNotes[128]); + SavesManager::syncBitFlags(s, &_quests[0], &_quests[64]); + + for (int i = 0; i < 85; ++i) + s.syncAsByte(_questItems[i]); + + for (int i = 0; ITEMS_COUNT; ++i) + _blacksmithWeapons2[i].synchronize(s); + for (int i = 0; ITEMS_COUNT; ++i) + _blacksmithArmor2[i].synchronize(s); + for (int i = 0; ITEMS_COUNT; ++i) + _blacksmithAccessories2[i].synchronize(s); + for (int i = 0; ITEMS_COUNT; ++i) + _blacksmithMisc2[i].synchronize(s); + + SavesManager::syncBitFlags(s, &_characterFlags[0][0], &_characterFlags[30][24]); + s.syncBytes(&dummy[0], 30); +} + +/*------------------------------------------------------------------------*/ + +PlayerStruct::PlayerStruct() { + _sex = MALE; + _race = HUMAN; + _xeenSide = 0; + _class = KNIGHT; + _ACTemp = 0; + _dbDay = 0; + _tempAge = 0; + Common::fill(&_skills[0], &_skills[18], 0); + Common::fill(&_awards[0], &_awards[64], false); + Common::fill(&_spells[9], &_spells[40], false); + _lloydMap = 0; + _hasSpells = false; + _currentSpell = 0; + _quickOption = 0; + _lloydSide = 0; + Common::fill(&_conditions[0], &_conditions[16], 0); + _townUnknown = 0; + _unknown2 = 0; + _currentHp = 0; + _currentSp = 0; + _ybDay = 0; + _experience = 0; + _currentAdventuringSpell = 0; + _currentCombatSpell = 0; +} + +void PlayerStruct::synchronize(Common::Serializer &s) { + char name[16]; + Common::fill(&name[0], &name[16], '\0'); + strncpy(name, _name.c_str(), 16); + s.syncBytes((byte *)name, 16); + + if (s.isLoading()) + _name = Common::String(name); + + s.syncAsByte(_sex); + s.syncAsByte(_race); + s.syncAsByte(_xeenSide); + s.syncAsByte(_class); + + _might.synchronize(s); + _intellect.synchronize(s); + _personality.synchronize(s); + _endurance.synchronize(s); + _speed.synchronize(s); + _accuracy.synchronize(s); + _luck.synchronize(s); + s.syncAsByte(_ACTemp); + _level.synchronize(s); + s.syncAsByte(_dbDay); + s.syncAsByte(_tempAge); + + for (int i = 0; i < 18; ++i) + s.syncAsByte(_skills[i]); + SavesManager::syncBitFlags(s, &_awards[0], &_awards[64]); + SavesManager::syncBitFlags(s, &_spells[0], &_spells[40]); + + s.syncAsByte(_lloydMap); + s.syncAsByte(_lloydPosition.x); + s.syncAsByte(_lloydPosition.y); + s.syncAsByte(_hasSpells); + s.syncAsByte(_currentSpell); + s.syncAsByte(_quickOption); + + for (int i = 0; i < 9; ++i) + _weapons[i].synchronize(s); + for (int i = 0; i < 9; ++i) + _armor[i].synchronize(s); + for (int i = 0; i < 9; ++i) + _accessories[i].synchronize(s); + for (int i = 0; i < 9; ++i) + _misc[i].synchronize(s); + + s.syncAsByte(_lloydSide); + _fireResistence.synchronize(s); + _coldResistence.synchronize(s); + _electricityResistence.synchronize(s); + _poisonResistence.synchronize(s); + _energyResistence.synchronize(s); + _magicResistence.synchronize(s); + + for (int i = 0; i < 16; ++i) + s.syncAsByte(_conditions[i]); + + s.syncAsUint16LE(_townUnknown); + s.syncAsByte(_unknown2); + s.syncAsUint16LE(_currentHp); + s.syncAsUint16LE(_currentSp); + s.syncAsUint16LE(_ybDay); + s.syncAsUint32LE(_experience); + s.syncAsByte(_currentAdventuringSpell); + s.syncAsByte(_currentCombatSpell); +} + +/*------------------------------------------------------------------------*/ + +/** + * Synchronizes a boolean array as a bitfield set + */ +void SavesManager::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP) { + byte data = 0; + + int bitCounter = 0; + for (bool *p = startP; p <= endP; ++p, ++bitCounter) { + if (bitCounter != 0 && (bitCounter % 8) == 0) { + s.syncAsByte(data); + if (p == endP) + break; + + if (s.isSaving()) + data = 0; + } + + if (s.isLoading()) + *p = (data >> bitCounter) != 0; + else if (*p) + data |= 1 << bitCounter; + } +} + +/*------------------------------------------------------------------------*/ + + +} // End of namespace Xeen diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h new file mode 100644 index 0000000000..ef12efde7a --- /dev/null +++ b/engines/xeen/saves.h @@ -0,0 +1,190 @@ +/* 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 XEEN_SAVES_H +#define XEEN_SAVES_H + +#include "common/scummsys.h" +#include "common/rect.h" +#include "common/savefile.h" +#include "xeen/items.h" + +namespace Xeen { + +enum Direction { DIR_NORTH = 0, DIR_EAST = 1, DIR_SOUTH = 2, DIR_WEST = 3 }; + +enum Difficulty { ADVENTURER = 0, WARRIOR = 1 }; + +enum Sex { MALE = 0, FEMALE = 1, YES_PLEASE = 2 }; + +enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 }; + +enum CharacterClass { KNIGHT = 0, PALADIN = 1, ARCHER = 2, CLERIC = 3, + SORCERER = 4, ROBBER = 5, NINJA = 6, BARBARIAN = 7, DRUID = 8, RANGER = 9 +}; + +enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3, + CARTOGRAPHER = 4, CRUSADER = 5, DIRECTION_SENSE = 6, LINGUIST = 7, + MERCHANT = 8, MOUNTAINEER = 9, NAVIGATOR = 10, PATHFINDER = 11, + PRAYER_MASTER = 12, PRESTIDIGITATION = 13, SWIMMING = 14, TRACKING = 15, + SPOT_DOORS = 16, DANGER_SENSE = 17 +}; + +enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, + DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, + DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11 +}; + +#define ITEMS_COUNT 36 + +class Roster { +public: + int _partyCount; + int _realPartyCount; + int _partyMembers[8]; + Direction _mazeDirection; + Common::Point _mazePosition; + int _mazeId; + int _priorMazeId; + bool _levitateActive; + bool _automapOn; + bool _wizardEyeActive; + bool _clairvoyanceActive; + bool _walkOnWaterActive; + bool _blessedActive; + bool _powerShieldActive; + bool _holyBonusActive; + bool _heroismActive; + Difficulty _difficulty; + XeenItem _blacksmithWeapons[ITEMS_COUNT]; + XeenItem _blacksmithArmor[ITEMS_COUNT]; + XeenItem _blacksmithAccessories[ITEMS_COUNT]; + XeenItem _blacksmithMisc[ITEMS_COUNT]; + bool _cloudsEnd; + bool _darkSideEnd; + bool _worldEnd; + int hour_maybe; + int _day; + int _year; + int _minutes; + int _food; + int _lightCount; + int _torchCount; + int _fireResistence; + int _electricityResistence; + int _coldResistence; + int _poisonResistence; + int _deathCount; + int _winCount; + int _lossCount; + int _gold; + int _gems; + int _bankGold; + int _bankGems; + int _totalTime; + bool _rested; + bool _gameFlags[256]; + bool _autoNotes[128]; + bool _quests[64]; + int _questItems[85]; + XeenItem _blacksmithWeapons2[ITEMS_COUNT]; + XeenItem _blacksmithArmor2[ITEMS_COUNT]; + XeenItem _blacksmithAccessories2[ITEMS_COUNT]; + XeenItem _blacksmithMisc2[ITEMS_COUNT]; + bool _characterFlags[30][24]; +public: + Roster(); + + void synchronize(Common::Serializer &s); +}; + +class AttributePair { +public: + int _permanent; + int _temporary; +public: + AttributePair(); + void synchronize(Common::Serializer &s); +}; + +class PlayerStruct { +public: + Common::String _name; + Sex _sex; + Race _race; + int _xeenSide; + CharacterClass _class; + AttributePair _might; + AttributePair _intellect; + AttributePair _personality; + AttributePair _endurance; + AttributePair _speed; + AttributePair _accuracy; + AttributePair _luck; + int _ACTemp; + AttributePair _level; + int _dbDay; + int _tempAge; + int _skills[18]; + bool _awards[64]; + bool _spells[40]; + int _lloydMap; + Common::Point _lloydPosition; + bool _hasSpells; + int _currentSpell; + int _quickOption; + XeenItem _weapons[9]; + XeenItem _armor[9]; + XeenItem _accessories[9]; + XeenItem _misc[9]; + int _lloydSide; + AttributePair _fireResistence; + AttributePair _coldResistence; + AttributePair _electricityResistence; + AttributePair _poisonResistence; + AttributePair _energyResistence; + AttributePair _magicResistence; + int _conditions[16]; + int _townUnknown; + int _unknown2; + int _currentHp; + int _currentSp; + int _ybDay; + uint32 _experience; + int _currentAdventuringSpell; + int _currentCombatSpell; +public: + PlayerStruct(); + void synchronize(Common::Serializer &s); +}; + +class SavesManager { +public: + Roster _roster; + Common::Array<PlayerStruct> _conditions; +public: + static void syncBitFlags(Common::Serializer &s, bool *startP, bool *endP); +}; + +} // End of namespace Xeen + +#endif /* XEEN_SAVES_H */ diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index b61d6a6cc2..35b4188c06 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -82,6 +82,14 @@ void XeenEngine::initialize() { Common::Error XeenEngine::run() { initialize(); + showIntro(); + if (shouldQuit()) + return Common::kNoError; + + showMainMenu(); + if (shouldQuit()) + return Common::kNoError; + playGame(); return Common::kNoError; @@ -220,8 +228,21 @@ void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeade // out->writeUint32LE(_events->getFrameCounter()); } +void XeenEngine::showIntro() { + +} + +void XeenEngine::showMainMenu() { + //OptionsMenu::show(this); +} + void XeenEngine::playGame() { - OptionsMenu::show(this); + +} + +void XeenEngine::drawUI() { + SpriteResource sprites1("global.icn"), borderSprites("border.icn"); + } } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 1b99a85a4b..2049888a9b 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -88,6 +88,12 @@ private: const XeenGameDescription *_gameDescription; Common::RandomSource _randomSource; int _loadSaveSlot; + + void showIntro(); + + void showMainMenu(); + + void drawUI(); protected: /** * Play the game -- cgit v1.2.3 From feacce66b92f17c655d70ec2cc233fc63feb517c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 2 Jan 2015 11:01:41 -1000 Subject: XEEN: Implemented dynamic data loading for new games --- engines/xeen/files.cpp | 52 +++++++--------------------------- engines/xeen/files.h | 45 ++++++++++++++++++++++++++++-- engines/xeen/saves.cpp | 76 +++++++++++++++++++++++++++++++++++--------------- engines/xeen/saves.h | 28 +++++++++++++++---- engines/xeen/xeen.cpp | 6 +++- engines/xeen/xeen.h | 2 ++ 6 files changed, 135 insertions(+), 74 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index 27bbf6e399..107cde45a1 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -29,45 +29,8 @@ namespace Xeen { -/** - * Xeen CC file implementation - */ -class CCArchive : public Common::Archive { -private: - /** - * Details of a single entry in a CC file index - */ - struct CCEntry { - uint16 _id; - uint32 _offset; - uint16 _size; - - CCEntry() : _id(0), _offset(0), _size(0) {} - CCEntry(uint16 id, uint32 offset, uint32 size) - : _id(id), _offset(offset), _size(size) { - } - }; - - Common::Array<CCEntry> _index; - Common::String _filename; - - uint16 convertNameToId(const Common::String &resourceName) const; - - void loadIndex(Common::SeekableReadStream *stream); - - bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const; -public: - CCArchive(const Common::String &filename); - virtual ~CCArchive(); - - // Archive implementation - virtual bool hasFile(const Common::String &name) const; - virtual int listMembers(Common::ArchiveMemberList &list) const; - virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const; - virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; -}; - -CCArchive::CCArchive(const Common::String &filename): _filename(filename) { +CCArchive::CCArchive(const Common::String &filename, bool encoded): + _filename(filename), _encoded(encoded) { File f(filename); loadIndex(&f); } @@ -107,9 +70,11 @@ Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::S byte *data = new byte[ccEntry._size]; f.read(data, ccEntry._size); - // Decrypt the data - for (int i = 0; i < ccEntry._size; ++i) - data[i] ^= 0x35; + if (_encoded) { + // Decrypt the data + for (int i = 0; i < ccEntry._size; ++i) + data[i] ^= 0x35; + } // Return the data as a stream return new Common::MemoryReadStream(data, ccEntry._size, DisposeAfterUse::YES); @@ -192,6 +157,9 @@ bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEn /*------------------------------------------------------------------------*/ +/** + * Instantiates the resource manager + */ void FileManager::init(XeenEngine *vm) { Common::File f; diff --git a/engines/xeen/files.h b/engines/xeen/files.h index 7ef126e01d..8a028a95c7 100644 --- a/engines/xeen/files.h +++ b/engines/xeen/files.h @@ -33,11 +33,11 @@ namespace Xeen { class XeenEngine; +/* + * Main resource manager + */ class FileManager { public: - /** - * Instantiates the resource manager - */ static void init(XeenEngine *vm); }; @@ -53,6 +53,45 @@ public: void openFile(const Common::String &filename); }; +/** +* Xeen CC file implementation +*/ +class CCArchive : public Common::Archive { +private: + /** + * Details of a single entry in a CC file index + */ + struct CCEntry { + uint16 _id; + uint32 _offset; + uint16 _size; + + CCEntry() : _id(0), _offset(0), _size(0) {} + CCEntry(uint16 id, uint32 offset, uint32 size) + : _id(id), _offset(offset), _size(size) { + } + }; + + Common::Array<CCEntry> _index; + Common::String _filename; + bool _encoded; + + uint16 convertNameToId(const Common::String &resourceName) const; + + void loadIndex(Common::SeekableReadStream *stream); + + bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const; +public: + CCArchive(const Common::String &filename, bool encoded = true); + virtual ~CCArchive(); + + // Archive implementation + virtual bool hasFile(const Common::String &name) const; + virtual int listMembers(Common::ArchiveMemberList &list) const; + virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const; + virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; +}; + } // End of namespace Xeen #endif /* XEEN_FILES_H */ diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index af74b58037..771affc6bc 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -23,6 +23,8 @@ #include "common/scummsys.h" #include "common/algorithm.h" #include "xeen/saves.h" +#include "xeen/files.h" +#include "xeen/xeen.h" namespace Xeen { @@ -37,7 +39,7 @@ void AttributePair::synchronize(Common::Serializer &s) { /*------------------------------------------------------------------------*/ -Roster::Roster() { +Party::Party() { _partyCount = 0; _realPartyCount = 0; Common::fill(&_partyMembers[0], &_partyMembers[8], 0); @@ -76,14 +78,17 @@ Roster::Roster() { _bankGems = 0; _totalTime = 0; _rested = false; - Common::fill(&_gameFlags[0], &_gameFlags[256], false); + + Common::fill(&_gameFlags[0], &_gameFlags[512], false); Common::fill(&_autoNotes[0], &_autoNotes[128], false); Common::fill(&_quests[0], &_quests[64], false); - Common::fill(&_questItems[0], &_questItems[65], 0); - Common::fill(&_characterFlags[0][0], &_characterFlags[30][24], false); + Common::fill(&_questItems[0], &_questItems[85], 0); + + for (int i = 0; i < TOTAL_CHARACTERS; ++i) + Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false); } -void Roster::synchronize(Common::Serializer &s) { +void Party::synchronize(Common::Serializer &s) { byte dummy[30]; Common::fill(&dummy[0], &dummy[30], 0); @@ -111,13 +116,13 @@ void Roster::synchronize(Common::Serializer &s) { s.syncAsByte(_heroismActive); s.syncAsByte(_difficulty); - for (int i = 0; ITEMS_COUNT; ++i) + for (int i = 0; i < ITEMS_COUNT; ++i) _blacksmithWeapons[i].synchronize(s); - for (int i = 0; ITEMS_COUNT; ++i) + for (int i = 0; i < ITEMS_COUNT; ++i) _blacksmithArmor[i].synchronize(s); - for (int i = 0; ITEMS_COUNT; ++i) + for (int i = 0; i < ITEMS_COUNT; ++i) _blacksmithAccessories[i].synchronize(s); - for (int i = 0; ITEMS_COUNT; ++i) + for (int i = 0; i < ITEMS_COUNT; ++i) _blacksmithMisc[i].synchronize(s); s.syncAsUint16LE(_cloudsEnd); @@ -150,16 +155,17 @@ void Roster::synchronize(Common::Serializer &s) { for (int i = 0; i < 85; ++i) s.syncAsByte(_questItems[i]); - for (int i = 0; ITEMS_COUNT; ++i) + for (int i = 0; i < ITEMS_COUNT; ++i) _blacksmithWeapons2[i].synchronize(s); - for (int i = 0; ITEMS_COUNT; ++i) + for (int i = 0; i < ITEMS_COUNT; ++i) _blacksmithArmor2[i].synchronize(s); - for (int i = 0; ITEMS_COUNT; ++i) + for (int i = 0; i < ITEMS_COUNT; ++i) _blacksmithAccessories2[i].synchronize(s); - for (int i = 0; ITEMS_COUNT; ++i) + for (int i = 0; i < ITEMS_COUNT; ++i) _blacksmithMisc2[i].synchronize(s); - SavesManager::syncBitFlags(s, &_characterFlags[0][0], &_characterFlags[30][24]); + for (int i = 0; i < TOTAL_CHARACTERS; ++i) + SavesManager::syncBitFlags(s, &_characterFlags[i][0], &_characterFlags[i][24]); s.syncBytes(&dummy[0], 30); } @@ -174,8 +180,8 @@ PlayerStruct::PlayerStruct() { _dbDay = 0; _tempAge = 0; Common::fill(&_skills[0], &_skills[18], 0); - Common::fill(&_awards[0], &_awards[64], false); - Common::fill(&_spells[9], &_spells[40], false); + Common::fill(&_awards[0], &_awards[512], false); + Common::fill(&_spells[9], &_spells[312], false); _lloydMap = 0; _hasSpells = false; _currentSpell = 0; @@ -220,8 +226,8 @@ void PlayerStruct::synchronize(Common::Serializer &s) { for (int i = 0; i < 18; ++i) s.syncAsByte(_skills[i]); - SavesManager::syncBitFlags(s, &_awards[0], &_awards[64]); - SavesManager::syncBitFlags(s, &_spells[0], &_spells[40]); + SavesManager::syncBitFlags(s, &_awards[0], &_awards[512]); + SavesManager::syncBitFlags(s, &_spells[0], &_spells[312]); s.syncAsByte(_lloydMap); s.syncAsByte(_lloydPosition.x); @@ -262,6 +268,16 @@ void PlayerStruct::synchronize(Common::Serializer &s) { /*------------------------------------------------------------------------*/ +void Roster::synchronize(Common::Serializer &s) { + if (s.isLoading()) + resize(30); + + for (uint i = 0; i < 30; ++i) + (*this)[i].synchronize(s); +} + +/*------------------------------------------------------------------------*/ + /** * Synchronizes a boolean array as a bitfield set */ @@ -269,9 +285,10 @@ void SavesManager::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP) byte data = 0; int bitCounter = 0; - for (bool *p = startP; p <= endP; ++p, ++bitCounter) { - if (bitCounter != 0 && (bitCounter % 8) == 0) { - s.syncAsByte(data); + for (bool *p = startP; p <= endP; ++p, bitCounter = (bitCounter + 1) % 8) { + if (p == endP || bitCounter == 0) { + if (p != endP || s.isSaving()) + s.syncAsByte(data); if (p == endP) break; @@ -286,7 +303,22 @@ void SavesManager::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP) } } -/*------------------------------------------------------------------------*/ +/** + * Sets up the dynamic data for the game for a new game + */ +void SavesManager::reset() { + Common::String name(_vm->getGameID() == GType_Clouds ? "xeen.cur" : "dark.cur"); + CCArchive cur(name, false); + + Common::SeekableReadStream *chr = cur.createReadStreamForMember("maze.chr"); + Common::Serializer sChr(chr, nullptr); + _roster.synchronize(sChr); + delete chr; + Common::SeekableReadStream *pty = cur.createReadStreamForMember("maze.pty"); + Common::Serializer sPty(pty, nullptr); + _party.synchronize(sPty); + delete pty; +} } // End of namespace Xeen diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h index ef12efde7a..3d8978e25a 100644 --- a/engines/xeen/saves.h +++ b/engines/xeen/saves.h @@ -55,8 +55,11 @@ enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, }; #define ITEMS_COUNT 36 +#define TOTAL_CHARACTERS 30 -class Roster { +class XeenEngine; + +class Party { public: int _partyCount; int _realPartyCount; @@ -102,7 +105,7 @@ public: int _bankGems; int _totalTime; bool _rested; - bool _gameFlags[256]; + bool _gameFlags[512]; bool _autoNotes[128]; bool _quests[64]; int _questItems[85]; @@ -112,7 +115,7 @@ public: XeenItem _blacksmithMisc2[ITEMS_COUNT]; bool _characterFlags[30][24]; public: - Roster(); + Party(); void synchronize(Common::Serializer &s); }; @@ -145,8 +148,8 @@ public: int _dbDay; int _tempAge; int _skills[18]; - bool _awards[64]; - bool _spells[40]; + bool _awards[512]; + bool _spells[312]; int _lloydMap; Common::Point _lloydPosition; bool _hasSpells; @@ -177,12 +180,25 @@ public: void synchronize(Common::Serializer &s); }; +class Roster: public Common::Array<PlayerStruct> { +public: + Roster() {} + + void synchronize(Common::Serializer &s); +}; + class SavesManager { +private: + XeenEngine *_vm; public: + Party _party; Roster _roster; - Common::Array<PlayerStruct> _conditions; public: static void syncBitFlags(Common::Serializer &s, bool *startP, bool *endP); +public: + SavesManager(XeenEngine *vm) : _vm(vm) {} + + void reset(); }; } // End of namespace Xeen diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 35b4188c06..96a4f5f3cf 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -37,6 +37,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) : _gameDescription(gameDesc), Engine(syst), _randomSource("Xeen") { _debugger = nullptr; _events = nullptr; + _saves = nullptr; _screen = nullptr; _sound = nullptr; _eventData = nullptr; @@ -45,6 +46,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) XeenEngine::~XeenEngine() { delete _debugger; delete _events; + delete _saves; delete _screen; delete _sound; delete _eventData; @@ -61,6 +63,7 @@ void XeenEngine::initialize() { FileManager::init(this); _debugger = new Debugger(this); _events = new EventsManager(this); + _saves = new SavesManager(this); _screen = new Screen(this); _screen->setupWindows(); _sound = new SoundManager(this); @@ -237,7 +240,8 @@ void XeenEngine::showMainMenu() { } void XeenEngine::playGame() { - + _saves->reset(); +// drawUI(); } void XeenEngine::drawUI() { diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 2049888a9b..7d23fded23 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -34,6 +34,7 @@ #include "graphics/surface.h" #include "xeen/debugger.h" #include "xeen/events.h" +#include "xeen/saves.h" #include "xeen/screen.h" #include "xeen/sound.h" @@ -119,6 +120,7 @@ private: public: Debugger *_debugger; EventsManager *_events; + SavesManager *_saves; Screen *_screen; SoundManager *_sound; Mode _mode; -- cgit v1.2.3 From bef5dbdc0a8640e3d51af5f1ef9ceb92ab930900 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 2 Jan 2015 11:29:15 -1000 Subject: XEEN: Replaced conditions array with named field structure --- engines/xeen/saves.cpp | 44 +++++++++++++++++++++++++++++++++++++++++--- engines/xeen/saves.h | 27 +++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 5 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index 771affc6bc..b3f1b4c71e 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -171,6 +171,46 @@ void Party::synchronize(Common::Serializer &s) { /*------------------------------------------------------------------------*/ +Conditions::Conditions() { + _cursed = 0; + _heartBroken = 0; + _weak = 0; + _poisoned = 0; + _diseased = 0; + _insane = 0; + _inLove = 0; + _drunk = 0; + _asleep = 0; + _depressed = 0; + _confused = 0; + _paralyzed = 0; + _unconscious = 0; + _dead = 0; + _stoned = 0; + _eradicated = 0; +} + +void Conditions::synchronize(Common::Serializer &s) { + s.syncAsByte(_cursed); + s.syncAsByte(_heartBroken); + s.syncAsByte(_weak); + s.syncAsByte(_poisoned); + s.syncAsByte(_diseased); + s.syncAsByte(_insane); + s.syncAsByte(_inLove); + s.syncAsByte(_drunk); + s.syncAsByte(_asleep); + s.syncAsByte(_depressed); + s.syncAsByte(_confused); + s.syncAsByte(_paralyzed); + s.syncAsByte(_unconscious); + s.syncAsByte(_dead); + s.syncAsByte(_stoned); + s.syncAsByte(_eradicated); +} + +/*------------------------------------------------------------------------*/ + PlayerStruct::PlayerStruct() { _sex = MALE; _race = HUMAN; @@ -187,7 +227,6 @@ PlayerStruct::PlayerStruct() { _currentSpell = 0; _quickOption = 0; _lloydSide = 0; - Common::fill(&_conditions[0], &_conditions[16], 0); _townUnknown = 0; _unknown2 = 0; _currentHp = 0; @@ -253,8 +292,7 @@ void PlayerStruct::synchronize(Common::Serializer &s) { _energyResistence.synchronize(s); _magicResistence.synchronize(s); - for (int i = 0; i < 16; ++i) - s.syncAsByte(_conditions[i]); + _conditions.synchronize(s); s.syncAsUint16LE(_townUnknown); s.syncAsByte(_unknown2); diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h index 3d8978e25a..307582505f 100644 --- a/engines/xeen/saves.h +++ b/engines/xeen/saves.h @@ -49,7 +49,7 @@ enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3, SPOT_DOORS = 16, DANGER_SENSE = 17 }; -enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, +enum ConditionType { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11 }; @@ -129,6 +129,29 @@ public: void synchronize(Common::Serializer &s); }; +class Conditions { + byte _cursed; + byte _heartBroken; + byte _weak; + byte _poisoned; + byte _diseased; + byte _insane; + byte _inLove; + byte _drunk; + byte _asleep; + byte _depressed; + byte _confused; + byte _paralyzed; + byte _unconscious; + byte _dead; + byte _stoned; + byte _eradicated; +public: + Conditions(); + + void synchronize(Common::Serializer &s); +}; + class PlayerStruct { public: Common::String _name; @@ -166,7 +189,7 @@ public: AttributePair _poisonResistence; AttributePair _energyResistence; AttributePair _magicResistence; - int _conditions[16]; + Conditions _conditions; int _townUnknown; int _unknown2; int _currentHp; -- cgit v1.2.3 From 27e020cbf98d88373111bff0f1d6ed0e846b2311 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 2 Jan 2015 12:14:57 -1000 Subject: XEEN: Split char/party logic into it's own file --- engines/xeen/module.mk | 1 + engines/xeen/party.cpp | 317 +++++++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/party.h | 217 +++++++++++++++++++++++++++++++++ engines/xeen/saves.h | 183 +--------------------------- engines/xeen/xeen.cpp | 12 +- engines/xeen/xeen.h | 2 + 6 files changed, 549 insertions(+), 183 deletions(-) create mode 100644 engines/xeen/party.cpp create mode 100644 engines/xeen/party.h (limited to 'engines/xeen') diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 2f5a092ca9..752608a136 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -12,6 +12,7 @@ MODULE_OBJS := \ files.o \ font.o \ items.o \ + party.o \ resdata.o \ resources.o \ saves.o \ diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp new file mode 100644 index 0000000000..69a64bb9c7 --- /dev/null +++ b/engines/xeen/party.cpp @@ -0,0 +1,317 @@ +/* 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/scummsys.h" +#include "common/algorithm.h" +#include "xeen/party.h" +#include "xeen/files.h" +#include "xeen/xeen.h" + +namespace Xeen { + +AttributePair::AttributePair() { + _temporary = _permanent = 0; +} + +void AttributePair::synchronize(Common::Serializer &s) { + s.syncAsByte(_permanent); + s.syncAsByte(_temporary); +} + +/*------------------------------------------------------------------------*/ + +Party::Party() { + _partyCount = 0; + _realPartyCount = 0; + Common::fill(&_partyMembers[0], &_partyMembers[8], 0); + _mazeDirection = DIR_NORTH; + _mazeId = _priorMazeId = 0; + _levitateActive = false; + _automapOn = false; + _wizardEyeActive = false; + _clairvoyanceActive = false; + _walkOnWaterActive = false; + _blessedActive = false; + _powerShieldActive = false; + _holyBonusActive = false; + _heroismActive = false; + _difficulty = ADVENTURER; + _cloudsEnd = false; + _darkSideEnd = false; + _worldEnd = false; + hour_maybe = 0; + _day = 0; + _year = 0; + _minutes = 0; + _food = 0; + _lightCount = 0; + _torchCount = 0; + _fireResistence = 0; + _electricityResistence = 0; + _coldResistence = 0; + _poisonResistence = 0; + _deathCount = 0; + _winCount = 0; + _lossCount = 0; + _gold = 0; + _gems = 0; + _bankGold = 0; + _bankGems = 0; + _totalTime = 0; + _rested = false; + + Common::fill(&_gameFlags[0], &_gameFlags[512], false); + Common::fill(&_autoNotes[0], &_autoNotes[128], false); + Common::fill(&_quests[0], &_quests[64], false); + Common::fill(&_questItems[0], &_questItems[85], 0); + + for (int i = 0; i < TOTAL_CHARACTERS; ++i) + Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false); +} + +void Party::synchronize(Common::Serializer &s) { + byte dummy[30]; + Common::fill(&dummy[0], &dummy[30], 0); + + s.syncAsByte(_partyCount); + s.syncAsByte(_realPartyCount); + for (int i = 0; i < 8; ++i) + s.syncAsByte(_partyMembers[i]); + s.syncAsByte(_mazeDirection); + s.syncAsByte(_mazePosition.x); + s.syncAsByte(_mazePosition.y); + s.syncAsByte(_mazeId); + + // Game configuration flags not used in this implementation + s.syncBytes(dummy, 3); + + s.syncAsByte(_priorMazeId); + s.syncAsByte(_levitateActive); + s.syncAsByte(_automapOn); + s.syncAsByte(_wizardEyeActive); + s.syncAsByte(_clairvoyanceActive); + s.syncAsByte(_walkOnWaterActive); + s.syncAsByte(_blessedActive); + s.syncAsByte(_powerShieldActive); + s.syncAsByte(_holyBonusActive); + s.syncAsByte(_heroismActive); + s.syncAsByte(_difficulty); + + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithWeapons[i].synchronize(s); + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithArmor[i].synchronize(s); + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithAccessories[i].synchronize(s); + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithMisc[i].synchronize(s); + + s.syncAsUint16LE(_cloudsEnd); + s.syncAsUint16LE(_darkSideEnd); + s.syncAsUint16LE(_worldEnd); + s.syncAsUint16LE(hour_maybe); + s.syncAsUint16LE(_day); + s.syncAsUint16LE(_year); + s.syncAsUint16LE(_minutes); + s.syncAsUint16LE(_food); + s.syncAsUint16LE(_lightCount); + s.syncAsUint16LE(_torchCount); + s.syncAsUint16LE(_fireResistence); + s.syncAsUint16LE(_electricityResistence); + s.syncAsUint16LE(_coldResistence); + s.syncAsUint16LE(_poisonResistence); + s.syncAsUint16LE(_deathCount); + s.syncAsUint16LE(_winCount); + s.syncAsUint16LE(_lossCount); + s.syncAsUint32LE(_gold); + s.syncAsUint32LE(_gems); + s.syncAsUint32LE(_bankGold); + s.syncAsUint32LE(_bankGems); + s.syncAsUint32LE(_totalTime); + s.syncAsByte(_rested); + SavesManager::syncBitFlags(s, &_gameFlags[0], &_gameFlags[512]); + SavesManager::syncBitFlags(s, &_autoNotes[0], &_autoNotes[128]); + SavesManager::syncBitFlags(s, &_quests[0], &_quests[64]); + + for (int i = 0; i < 85; ++i) + s.syncAsByte(_questItems[i]); + + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithWeapons2[i].synchronize(s); + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithArmor2[i].synchronize(s); + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithAccessories2[i].synchronize(s); + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithMisc2[i].synchronize(s); + + for (int i = 0; i < TOTAL_CHARACTERS; ++i) + SavesManager::syncBitFlags(s, &_characterFlags[i][0], &_characterFlags[i][24]); + s.syncBytes(&dummy[0], 30); +} + +/*------------------------------------------------------------------------*/ + +Conditions::Conditions() { + _cursed = 0; + _heartBroken = 0; + _weak = 0; + _poisoned = 0; + _diseased = 0; + _insane = 0; + _inLove = 0; + _drunk = 0; + _asleep = 0; + _depressed = 0; + _confused = 0; + _paralyzed = 0; + _unconscious = 0; + _dead = 0; + _stoned = 0; + _eradicated = 0; +} + +void Conditions::synchronize(Common::Serializer &s) { + s.syncAsByte(_cursed); + s.syncAsByte(_heartBroken); + s.syncAsByte(_weak); + s.syncAsByte(_poisoned); + s.syncAsByte(_diseased); + s.syncAsByte(_insane); + s.syncAsByte(_inLove); + s.syncAsByte(_drunk); + s.syncAsByte(_asleep); + s.syncAsByte(_depressed); + s.syncAsByte(_confused); + s.syncAsByte(_paralyzed); + s.syncAsByte(_unconscious); + s.syncAsByte(_dead); + s.syncAsByte(_stoned); + s.syncAsByte(_eradicated); +} + +/*------------------------------------------------------------------------*/ + +PlayerStruct::PlayerStruct() { + _sex = MALE; + _race = HUMAN; + _xeenSide = 0; + _class = KNIGHT; + _ACTemp = 0; + _dbDay = 0; + _tempAge = 0; + Common::fill(&_skills[0], &_skills[18], 0); + Common::fill(&_awards[0], &_awards[512], false); + Common::fill(&_spells[9], &_spells[312], false); + _lloydMap = 0; + _hasSpells = false; + _currentSpell = 0; + _quickOption = 0; + _lloydSide = 0; + _townUnknown = 0; + _unknown2 = 0; + _currentHp = 0; + _currentSp = 0; + _ybDay = 0; + _experience = 0; + _currentAdventuringSpell = 0; + _currentCombatSpell = 0; +} + +void PlayerStruct::synchronize(Common::Serializer &s) { + char name[16]; + Common::fill(&name[0], &name[16], '\0'); + strncpy(name, _name.c_str(), 16); + s.syncBytes((byte *)name, 16); + + if (s.isLoading()) + _name = Common::String(name); + + s.syncAsByte(_sex); + s.syncAsByte(_race); + s.syncAsByte(_xeenSide); + s.syncAsByte(_class); + + _might.synchronize(s); + _intellect.synchronize(s); + _personality.synchronize(s); + _endurance.synchronize(s); + _speed.synchronize(s); + _accuracy.synchronize(s); + _luck.synchronize(s); + s.syncAsByte(_ACTemp); + _level.synchronize(s); + s.syncAsByte(_dbDay); + s.syncAsByte(_tempAge); + + for (int i = 0; i < 18; ++i) + s.syncAsByte(_skills[i]); + SavesManager::syncBitFlags(s, &_awards[0], &_awards[512]); + SavesManager::syncBitFlags(s, &_spells[0], &_spells[312]); + + s.syncAsByte(_lloydMap); + s.syncAsByte(_lloydPosition.x); + s.syncAsByte(_lloydPosition.y); + s.syncAsByte(_hasSpells); + s.syncAsByte(_currentSpell); + s.syncAsByte(_quickOption); + + for (int i = 0; i < 9; ++i) + _weapons[i].synchronize(s); + for (int i = 0; i < 9; ++i) + _armor[i].synchronize(s); + for (int i = 0; i < 9; ++i) + _accessories[i].synchronize(s); + for (int i = 0; i < 9; ++i) + _misc[i].synchronize(s); + + s.syncAsByte(_lloydSide); + _fireResistence.synchronize(s); + _coldResistence.synchronize(s); + _electricityResistence.synchronize(s); + _poisonResistence.synchronize(s); + _energyResistence.synchronize(s); + _magicResistence.synchronize(s); + + _conditions.synchronize(s); + + s.syncAsUint16LE(_townUnknown); + s.syncAsByte(_unknown2); + s.syncAsUint16LE(_currentHp); + s.syncAsUint16LE(_currentSp); + s.syncAsUint16LE(_ybDay); + s.syncAsUint32LE(_experience); + s.syncAsByte(_currentAdventuringSpell); + s.syncAsByte(_currentCombatSpell); +} + +/*------------------------------------------------------------------------*/ + +void Roster::synchronize(Common::Serializer &s) { + if (s.isLoading()) + resize(30); + + for (uint i = 0; i < 30; ++i) + (*this)[i].synchronize(s); +} + +} // End of namespace Xeen diff --git a/engines/xeen/party.h b/engines/xeen/party.h new file mode 100644 index 0000000000..6a6ec5f8a1 --- /dev/null +++ b/engines/xeen/party.h @@ -0,0 +1,217 @@ +/* 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 XEEN_PARTY_H +#define XEEN_PARTY_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/rect.h" +#include "common/serializer.h" +#include "xeen/items.h" + +namespace Xeen { + +enum Direction { DIR_NORTH = 0, DIR_EAST = 1, DIR_SOUTH = 2, DIR_WEST = 3 }; + +enum Difficulty { ADVENTURER = 0, WARRIOR = 1 }; + +enum Sex { MALE = 0, FEMALE = 1, YES_PLEASE = 2 }; + +enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 }; + +enum CharacterClass { KNIGHT = 0, PALADIN = 1, ARCHER = 2, CLERIC = 3, + SORCERER = 4, ROBBER = 5, NINJA = 6, BARBARIAN = 7, DRUID = 8, RANGER = 9 +}; + +enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3, + CARTOGRAPHER = 4, CRUSADER = 5, DIRECTION_SENSE = 6, LINGUIST = 7, + MERCHANT = 8, MOUNTAINEER = 9, NAVIGATOR = 10, PATHFINDER = 11, + PRAYER_MASTER = 12, PRESTIDIGITATION = 13, SWIMMING = 14, TRACKING = 15, + SPOT_DOORS = 16, DANGER_SENSE = 17 +}; + +enum ConditionType { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, + DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, + DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11 +}; + +#define ITEMS_COUNT 36 +#define TOTAL_CHARACTERS 30 +#define MAX_ACTIVE_PARTY 6 + +class XeenEngine; + +class Party { +public: + int _partyCount; + int _realPartyCount; + int _partyMembers[8]; + Direction _mazeDirection; + Common::Point _mazePosition; + int _mazeId; + int _priorMazeId; + bool _levitateActive; + bool _automapOn; + bool _wizardEyeActive; + bool _clairvoyanceActive; + bool _walkOnWaterActive; + bool _blessedActive; + bool _powerShieldActive; + bool _holyBonusActive; + bool _heroismActive; + Difficulty _difficulty; + XeenItem _blacksmithWeapons[ITEMS_COUNT]; + XeenItem _blacksmithArmor[ITEMS_COUNT]; + XeenItem _blacksmithAccessories[ITEMS_COUNT]; + XeenItem _blacksmithMisc[ITEMS_COUNT]; + bool _cloudsEnd; + bool _darkSideEnd; + bool _worldEnd; + int hour_maybe; + int _day; + int _year; + int _minutes; + int _food; + int _lightCount; + int _torchCount; + int _fireResistence; + int _electricityResistence; + int _coldResistence; + int _poisonResistence; + int _deathCount; + int _winCount; + int _lossCount; + int _gold; + int _gems; + int _bankGold; + int _bankGems; + int _totalTime; + bool _rested; + bool _gameFlags[512]; + bool _autoNotes[128]; + bool _quests[64]; + int _questItems[85]; + XeenItem _blacksmithWeapons2[ITEMS_COUNT]; + XeenItem _blacksmithArmor2[ITEMS_COUNT]; + XeenItem _blacksmithAccessories2[ITEMS_COUNT]; + XeenItem _blacksmithMisc2[ITEMS_COUNT]; + bool _characterFlags[30][24]; +public: + Party(); + + void synchronize(Common::Serializer &s); +}; + +class AttributePair { +public: + int _permanent; + int _temporary; +public: + AttributePair(); + void synchronize(Common::Serializer &s); +}; + +class Conditions { + byte _cursed; + byte _heartBroken; + byte _weak; + byte _poisoned; + byte _diseased; + byte _insane; + byte _inLove; + byte _drunk; + byte _asleep; + byte _depressed; + byte _confused; + byte _paralyzed; + byte _unconscious; + byte _dead; + byte _stoned; + byte _eradicated; +public: + Conditions(); + + void synchronize(Common::Serializer &s); +}; + +class PlayerStruct { +public: + Common::String _name; + Sex _sex; + Race _race; + int _xeenSide; + CharacterClass _class; + AttributePair _might; + AttributePair _intellect; + AttributePair _personality; + AttributePair _endurance; + AttributePair _speed; + AttributePair _accuracy; + AttributePair _luck; + int _ACTemp; + AttributePair _level; + int _dbDay; + int _tempAge; + int _skills[18]; + bool _awards[512]; + bool _spells[312]; + int _lloydMap; + Common::Point _lloydPosition; + bool _hasSpells; + int _currentSpell; + int _quickOption; + XeenItem _weapons[9]; + XeenItem _armor[9]; + XeenItem _accessories[9]; + XeenItem _misc[9]; + int _lloydSide; + AttributePair _fireResistence; + AttributePair _coldResistence; + AttributePair _electricityResistence; + AttributePair _poisonResistence; + AttributePair _energyResistence; + AttributePair _magicResistence; + Conditions _conditions; + int _townUnknown; + int _unknown2; + int _currentHp; + int _currentSp; + int _ybDay; + uint32 _experience; + int _currentAdventuringSpell; + int _currentCombatSpell; +public: + PlayerStruct(); + void synchronize(Common::Serializer &s); +}; + +class Roster: public Common::Array<PlayerStruct> { +public: + Roster() {} + + void synchronize(Common::Serializer &s); +}; + +} // End of namespace Xeen + +#endif /* XEEN_PARTY_H */ diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h index 307582505f..8b29f15838 100644 --- a/engines/xeen/saves.h +++ b/engines/xeen/saves.h @@ -24,192 +24,11 @@ #define XEEN_SAVES_H #include "common/scummsys.h" -#include "common/rect.h" #include "common/savefile.h" -#include "xeen/items.h" +#include "xeen/party.h" namespace Xeen { -enum Direction { DIR_NORTH = 0, DIR_EAST = 1, DIR_SOUTH = 2, DIR_WEST = 3 }; - -enum Difficulty { ADVENTURER = 0, WARRIOR = 1 }; - -enum Sex { MALE = 0, FEMALE = 1, YES_PLEASE = 2 }; - -enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 }; - -enum CharacterClass { KNIGHT = 0, PALADIN = 1, ARCHER = 2, CLERIC = 3, - SORCERER = 4, ROBBER = 5, NINJA = 6, BARBARIAN = 7, DRUID = 8, RANGER = 9 -}; - -enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3, - CARTOGRAPHER = 4, CRUSADER = 5, DIRECTION_SENSE = 6, LINGUIST = 7, - MERCHANT = 8, MOUNTAINEER = 9, NAVIGATOR = 10, PATHFINDER = 11, - PRAYER_MASTER = 12, PRESTIDIGITATION = 13, SWIMMING = 14, TRACKING = 15, - SPOT_DOORS = 16, DANGER_SENSE = 17 -}; - -enum ConditionType { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, - DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, - DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11 -}; - -#define ITEMS_COUNT 36 -#define TOTAL_CHARACTERS 30 - -class XeenEngine; - -class Party { -public: - int _partyCount; - int _realPartyCount; - int _partyMembers[8]; - Direction _mazeDirection; - Common::Point _mazePosition; - int _mazeId; - int _priorMazeId; - bool _levitateActive; - bool _automapOn; - bool _wizardEyeActive; - bool _clairvoyanceActive; - bool _walkOnWaterActive; - bool _blessedActive; - bool _powerShieldActive; - bool _holyBonusActive; - bool _heroismActive; - Difficulty _difficulty; - XeenItem _blacksmithWeapons[ITEMS_COUNT]; - XeenItem _blacksmithArmor[ITEMS_COUNT]; - XeenItem _blacksmithAccessories[ITEMS_COUNT]; - XeenItem _blacksmithMisc[ITEMS_COUNT]; - bool _cloudsEnd; - bool _darkSideEnd; - bool _worldEnd; - int hour_maybe; - int _day; - int _year; - int _minutes; - int _food; - int _lightCount; - int _torchCount; - int _fireResistence; - int _electricityResistence; - int _coldResistence; - int _poisonResistence; - int _deathCount; - int _winCount; - int _lossCount; - int _gold; - int _gems; - int _bankGold; - int _bankGems; - int _totalTime; - bool _rested; - bool _gameFlags[512]; - bool _autoNotes[128]; - bool _quests[64]; - int _questItems[85]; - XeenItem _blacksmithWeapons2[ITEMS_COUNT]; - XeenItem _blacksmithArmor2[ITEMS_COUNT]; - XeenItem _blacksmithAccessories2[ITEMS_COUNT]; - XeenItem _blacksmithMisc2[ITEMS_COUNT]; - bool _characterFlags[30][24]; -public: - Party(); - - void synchronize(Common::Serializer &s); -}; - -class AttributePair { -public: - int _permanent; - int _temporary; -public: - AttributePair(); - void synchronize(Common::Serializer &s); -}; - -class Conditions { - byte _cursed; - byte _heartBroken; - byte _weak; - byte _poisoned; - byte _diseased; - byte _insane; - byte _inLove; - byte _drunk; - byte _asleep; - byte _depressed; - byte _confused; - byte _paralyzed; - byte _unconscious; - byte _dead; - byte _stoned; - byte _eradicated; -public: - Conditions(); - - void synchronize(Common::Serializer &s); -}; - -class PlayerStruct { -public: - Common::String _name; - Sex _sex; - Race _race; - int _xeenSide; - CharacterClass _class; - AttributePair _might; - AttributePair _intellect; - AttributePair _personality; - AttributePair _endurance; - AttributePair _speed; - AttributePair _accuracy; - AttributePair _luck; - int _ACTemp; - AttributePair _level; - int _dbDay; - int _tempAge; - int _skills[18]; - bool _awards[512]; - bool _spells[312]; - int _lloydMap; - Common::Point _lloydPosition; - bool _hasSpells; - int _currentSpell; - int _quickOption; - XeenItem _weapons[9]; - XeenItem _armor[9]; - XeenItem _accessories[9]; - XeenItem _misc[9]; - int _lloydSide; - AttributePair _fireResistence; - AttributePair _coldResistence; - AttributePair _electricityResistence; - AttributePair _poisonResistence; - AttributePair _energyResistence; - AttributePair _magicResistence; - Conditions _conditions; - int _townUnknown; - int _unknown2; - int _currentHp; - int _currentSp; - int _ybDay; - uint32 _experience; - int _currentAdventuringSpell; - int _currentCombatSpell; -public: - PlayerStruct(); - void synchronize(Common::Serializer &s); -}; - -class Roster: public Common::Array<PlayerStruct> { -public: - Roster() {} - - void synchronize(Common::Serializer &s); -}; - class SavesManager { private: XeenEngine *_vm; diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 96a4f5f3cf..45d9c22413 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -41,6 +41,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _screen = nullptr; _sound = nullptr; _eventData = nullptr; + Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr); } XeenEngine::~XeenEngine() { @@ -241,12 +242,21 @@ void XeenEngine::showMainMenu() { void XeenEngine::playGame() { _saves->reset(); -// drawUI(); + drawUI(); } +/* + * Lots of stuff in this method. + * TODO: Consider renaming method when better understood + */ void XeenEngine::drawUI() { SpriteResource sprites1("global.icn"), borderSprites("border.icn"); + // Get mappings to the active characters in the party + Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr); + for (int i = 0; i < _saves->_party._partyCount; ++i) { + _activeRoster[i] = &_saves->_roster[_saves->_party._partyMembers[i]]; + } } } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 7d23fded23..159ce7446b 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -34,6 +34,7 @@ #include "graphics/surface.h" #include "xeen/debugger.h" #include "xeen/events.h" +#include "xeen/party.h" #include "xeen/saves.h" #include "xeen/screen.h" #include "xeen/sound.h" @@ -126,6 +127,7 @@ public: Mode _mode; GameEvent _gameEvent; Common::SeekableReadStream *_eventData; + PlayerStruct *_activeRoster[MAX_ACTIVE_PARTY]; public: XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); virtual ~XeenEngine(); -- cgit v1.2.3 From 9a8cb48a9edcc67b17c192ff13b3d9d1e40f73a9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 2 Jan 2015 12:27:59 -1000 Subject: XEEN: Cleanup of party code split, moved roster and party to engine --- engines/xeen/party.cpp | 1 + engines/xeen/saves.cpp | 288 +------------------------------------------------ engines/xeen/saves.h | 18 +++- engines/xeen/xeen.cpp | 9 +- engines/xeen/xeen.h | 13 +-- 5 files changed, 25 insertions(+), 304 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 69a64bb9c7..c5f80eb1f5 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -25,6 +25,7 @@ #include "xeen/party.h" #include "xeen/files.h" #include "xeen/xeen.h" +#include "xeen/saves.h" namespace Xeen { diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index b3f1b4c71e..7482a12ff5 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -28,294 +28,10 @@ namespace Xeen { -AttributePair::AttributePair() { - _temporary = _permanent = 0; +SavesManager::SavesManager(XeenEngine *vm, Party &party, Roster &roster) : + _vm(vm), _party(party), _roster(roster) { } -void AttributePair::synchronize(Common::Serializer &s) { - s.syncAsByte(_permanent); - s.syncAsByte(_temporary); -} - -/*------------------------------------------------------------------------*/ - -Party::Party() { - _partyCount = 0; - _realPartyCount = 0; - Common::fill(&_partyMembers[0], &_partyMembers[8], 0); - _mazeDirection = DIR_NORTH; - _mazeId = _priorMazeId = 0; - _levitateActive = false; - _automapOn = false; - _wizardEyeActive = false; - _clairvoyanceActive = false; - _walkOnWaterActive = false; - _blessedActive = false; - _powerShieldActive = false; - _holyBonusActive = false; - _heroismActive = false; - _difficulty = ADVENTURER; - _cloudsEnd = false; - _darkSideEnd = false; - _worldEnd = false; - hour_maybe = 0; - _day = 0; - _year = 0; - _minutes = 0; - _food = 0; - _lightCount = 0; - _torchCount = 0; - _fireResistence = 0; - _electricityResistence = 0; - _coldResistence = 0; - _poisonResistence = 0; - _deathCount = 0; - _winCount = 0; - _lossCount = 0; - _gold = 0; - _gems = 0; - _bankGold = 0; - _bankGems = 0; - _totalTime = 0; - _rested = false; - - Common::fill(&_gameFlags[0], &_gameFlags[512], false); - Common::fill(&_autoNotes[0], &_autoNotes[128], false); - Common::fill(&_quests[0], &_quests[64], false); - Common::fill(&_questItems[0], &_questItems[85], 0); - - for (int i = 0; i < TOTAL_CHARACTERS; ++i) - Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false); -} - -void Party::synchronize(Common::Serializer &s) { - byte dummy[30]; - Common::fill(&dummy[0], &dummy[30], 0); - - s.syncAsByte(_partyCount); - s.syncAsByte(_realPartyCount); - for (int i = 0; i < 8; ++i) - s.syncAsByte(_partyMembers[i]); - s.syncAsByte(_mazeDirection); - s.syncAsByte(_mazePosition.x); - s.syncAsByte(_mazePosition.y); - s.syncAsByte(_mazeId); - - // Game configuration flags not used in this implementation - s.syncBytes(dummy, 3); - - s.syncAsByte(_priorMazeId); - s.syncAsByte(_levitateActive); - s.syncAsByte(_automapOn); - s.syncAsByte(_wizardEyeActive); - s.syncAsByte(_clairvoyanceActive); - s.syncAsByte(_walkOnWaterActive); - s.syncAsByte(_blessedActive); - s.syncAsByte(_powerShieldActive); - s.syncAsByte(_holyBonusActive); - s.syncAsByte(_heroismActive); - s.syncAsByte(_difficulty); - - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithWeapons[i].synchronize(s); - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithArmor[i].synchronize(s); - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithAccessories[i].synchronize(s); - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithMisc[i].synchronize(s); - - s.syncAsUint16LE(_cloudsEnd); - s.syncAsUint16LE(_darkSideEnd); - s.syncAsUint16LE(_worldEnd); - s.syncAsUint16LE(hour_maybe); - s.syncAsUint16LE(_day); - s.syncAsUint16LE(_year); - s.syncAsUint16LE(_minutes); - s.syncAsUint16LE(_food); - s.syncAsUint16LE(_lightCount); - s.syncAsUint16LE(_torchCount); - s.syncAsUint16LE(_fireResistence); - s.syncAsUint16LE(_electricityResistence); - s.syncAsUint16LE(_coldResistence); - s.syncAsUint16LE(_poisonResistence); - s.syncAsUint16LE(_deathCount); - s.syncAsUint16LE(_winCount); - s.syncAsUint16LE(_lossCount); - s.syncAsUint32LE(_gold); - s.syncAsUint32LE(_gems); - s.syncAsUint32LE(_bankGold); - s.syncAsUint32LE(_bankGems); - s.syncAsUint32LE(_totalTime); - s.syncAsByte(_rested); - SavesManager::syncBitFlags(s, &_gameFlags[0], &_gameFlags[512]); - SavesManager::syncBitFlags(s, &_autoNotes[0], &_autoNotes[128]); - SavesManager::syncBitFlags(s, &_quests[0], &_quests[64]); - - for (int i = 0; i < 85; ++i) - s.syncAsByte(_questItems[i]); - - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithWeapons2[i].synchronize(s); - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithArmor2[i].synchronize(s); - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithAccessories2[i].synchronize(s); - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithMisc2[i].synchronize(s); - - for (int i = 0; i < TOTAL_CHARACTERS; ++i) - SavesManager::syncBitFlags(s, &_characterFlags[i][0], &_characterFlags[i][24]); - s.syncBytes(&dummy[0], 30); -} - -/*------------------------------------------------------------------------*/ - -Conditions::Conditions() { - _cursed = 0; - _heartBroken = 0; - _weak = 0; - _poisoned = 0; - _diseased = 0; - _insane = 0; - _inLove = 0; - _drunk = 0; - _asleep = 0; - _depressed = 0; - _confused = 0; - _paralyzed = 0; - _unconscious = 0; - _dead = 0; - _stoned = 0; - _eradicated = 0; -} - -void Conditions::synchronize(Common::Serializer &s) { - s.syncAsByte(_cursed); - s.syncAsByte(_heartBroken); - s.syncAsByte(_weak); - s.syncAsByte(_poisoned); - s.syncAsByte(_diseased); - s.syncAsByte(_insane); - s.syncAsByte(_inLove); - s.syncAsByte(_drunk); - s.syncAsByte(_asleep); - s.syncAsByte(_depressed); - s.syncAsByte(_confused); - s.syncAsByte(_paralyzed); - s.syncAsByte(_unconscious); - s.syncAsByte(_dead); - s.syncAsByte(_stoned); - s.syncAsByte(_eradicated); -} - -/*------------------------------------------------------------------------*/ - -PlayerStruct::PlayerStruct() { - _sex = MALE; - _race = HUMAN; - _xeenSide = 0; - _class = KNIGHT; - _ACTemp = 0; - _dbDay = 0; - _tempAge = 0; - Common::fill(&_skills[0], &_skills[18], 0); - Common::fill(&_awards[0], &_awards[512], false); - Common::fill(&_spells[9], &_spells[312], false); - _lloydMap = 0; - _hasSpells = false; - _currentSpell = 0; - _quickOption = 0; - _lloydSide = 0; - _townUnknown = 0; - _unknown2 = 0; - _currentHp = 0; - _currentSp = 0; - _ybDay = 0; - _experience = 0; - _currentAdventuringSpell = 0; - _currentCombatSpell = 0; -} - -void PlayerStruct::synchronize(Common::Serializer &s) { - char name[16]; - Common::fill(&name[0], &name[16], '\0'); - strncpy(name, _name.c_str(), 16); - s.syncBytes((byte *)name, 16); - - if (s.isLoading()) - _name = Common::String(name); - - s.syncAsByte(_sex); - s.syncAsByte(_race); - s.syncAsByte(_xeenSide); - s.syncAsByte(_class); - - _might.synchronize(s); - _intellect.synchronize(s); - _personality.synchronize(s); - _endurance.synchronize(s); - _speed.synchronize(s); - _accuracy.synchronize(s); - _luck.synchronize(s); - s.syncAsByte(_ACTemp); - _level.synchronize(s); - s.syncAsByte(_dbDay); - s.syncAsByte(_tempAge); - - for (int i = 0; i < 18; ++i) - s.syncAsByte(_skills[i]); - SavesManager::syncBitFlags(s, &_awards[0], &_awards[512]); - SavesManager::syncBitFlags(s, &_spells[0], &_spells[312]); - - s.syncAsByte(_lloydMap); - s.syncAsByte(_lloydPosition.x); - s.syncAsByte(_lloydPosition.y); - s.syncAsByte(_hasSpells); - s.syncAsByte(_currentSpell); - s.syncAsByte(_quickOption); - - for (int i = 0; i < 9; ++i) - _weapons[i].synchronize(s); - for (int i = 0; i < 9; ++i) - _armor[i].synchronize(s); - for (int i = 0; i < 9; ++i) - _accessories[i].synchronize(s); - for (int i = 0; i < 9; ++i) - _misc[i].synchronize(s); - - s.syncAsByte(_lloydSide); - _fireResistence.synchronize(s); - _coldResistence.synchronize(s); - _electricityResistence.synchronize(s); - _poisonResistence.synchronize(s); - _energyResistence.synchronize(s); - _magicResistence.synchronize(s); - - _conditions.synchronize(s); - - s.syncAsUint16LE(_townUnknown); - s.syncAsByte(_unknown2); - s.syncAsUint16LE(_currentHp); - s.syncAsUint16LE(_currentSp); - s.syncAsUint16LE(_ybDay); - s.syncAsUint32LE(_experience); - s.syncAsByte(_currentAdventuringSpell); - s.syncAsByte(_currentCombatSpell); -} - -/*------------------------------------------------------------------------*/ - -void Roster::synchronize(Common::Serializer &s) { - if (s.isLoading()) - resize(30); - - for (uint i = 0; i < 30; ++i) - (*this)[i].synchronize(s); -} - -/*------------------------------------------------------------------------*/ - /** * Synchronizes a boolean array as a bitfield set */ diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h index 8b29f15838..f3ace80a03 100644 --- a/engines/xeen/saves.h +++ b/engines/xeen/saves.h @@ -25,21 +25,29 @@ #include "common/scummsys.h" #include "common/savefile.h" +#include "graphics/surface.h" #include "xeen/party.h" namespace Xeen { +struct XeenSavegameHeader { + uint8 _version; + Common::String _saveName; + Graphics::Surface *_thumbnail; + int _year, _month, _day; + int _hour, _minute; + int _totalFrames; +}; + class SavesManager { private: XeenEngine *_vm; -public: - Party _party; - Roster _roster; + Party &_party; + Roster &_roster; public: static void syncBitFlags(Common::Serializer &s, bool *startP, bool *endP); public: - SavesManager(XeenEngine *vm) : _vm(vm) {} - + SavesManager(XeenEngine *vm, Party &party, Roster &roster); void reset(); }; diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 45d9c22413..dfa05b0aa1 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -42,6 +42,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _sound = nullptr; _eventData = nullptr; Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr); + _isEarlyGame = false; } XeenEngine::~XeenEngine() { @@ -64,7 +65,7 @@ void XeenEngine::initialize() { FileManager::init(this); _debugger = new Debugger(this); _events = new EventsManager(this); - _saves = new SavesManager(this); + _saves = new SavesManager(this, _party, _roster); _screen = new Screen(this); _screen->setupWindows(); _sound = new SoundManager(this); @@ -254,9 +255,11 @@ void XeenEngine::drawUI() { // Get mappings to the active characters in the party Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr); - for (int i = 0; i < _saves->_party._partyCount; ++i) { - _activeRoster[i] = &_saves->_roster[_saves->_party._partyMembers[i]]; + for (int i = 0; i < _party._partyCount; ++i) { + _activeRoster[i] = &_roster[_party._partyMembers[i]]; } + + _isEarlyGame = _party._minutes >= 300; } } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 159ce7446b..787cc3d435 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -31,7 +31,6 @@ #include "common/serializer.h" #include "common/util.h" #include "engines/engine.h" -#include "graphics/surface.h" #include "xeen/debugger.h" #include "xeen/events.h" #include "xeen/party.h" @@ -76,20 +75,12 @@ struct XeenGameDescription; #define XEEN_SAVEGAME_VERSION 1 #define GAME_FRAME_TIME 50 -struct XeenSavegameHeader { - uint8 _version; - Common::String _saveName; - Graphics::Surface *_thumbnail; - int _year, _month, _day; - int _hour, _minute; - int _totalFrames; -}; - class XeenEngine : public Engine { private: const XeenGameDescription *_gameDescription; Common::RandomSource _randomSource; int _loadSaveSlot; + bool _isEarlyGame; void showIntro(); @@ -127,6 +118,8 @@ public: Mode _mode; GameEvent _gameEvent; Common::SeekableReadStream *_eventData; + Roster _roster; + Party _party; PlayerStruct *_activeRoster[MAX_ACTIVE_PARTY]; public: XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); -- cgit v1.2.3 From 21d981f8e86bf214daa2e203acc2fb20c82ec8a0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 2 Jan 2015 12:34:45 -1000 Subject: XEEN: Fix compiler warnings --- engines/xeen/darkside/darkside_game.cpp | 6 +++++- engines/xeen/debugger.cpp | 3 ++- engines/xeen/resources.cpp | 34 ++++++++++++++++----------------- 3 files changed, 24 insertions(+), 19 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp index c039d1ff0b..30f54580e3 100644 --- a/engines/xeen/darkside/darkside_game.cpp +++ b/engines/xeen/darkside/darkside_game.cpp @@ -181,7 +181,7 @@ void DarkSideEngine::showStartSequence() { int idx1 = 0; bool skipElapsed = false; uint32 timeExpired = 0; - bool fadeFlag = true; +// bool fadeFlag = true; for (int idx = 200; idx > 0; ) { _events->updateGameCounter(); @@ -218,6 +218,10 @@ void DarkSideEngine::showStartSequence() { _events->updateGameCounter(); pause(30); + + // TODO: More + _sound->playMusic(voc[0]); + _sound->playMusic(voc[1]); } } // End of namespace Xeen diff --git a/engines/xeen/debugger.cpp b/engines/xeen/debugger.cpp index aa4516e3bc..a83af9f99d 100644 --- a/engines/xeen/debugger.cpp +++ b/engines/xeen/debugger.cpp @@ -25,7 +25,7 @@ #include "xeen/debugger.h" namespace Xeen { - +/* static int strToInt(const char *s) { if (!*s) // No string at all @@ -41,6 +41,7 @@ static int strToInt(const char *s) { error("strToInt failed on string \"%s\"", s); return (int)tmp; } +*/ /*------------------------------------------------------------------------*/ diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index d1177dab00..de0804dc5c 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -26,42 +26,42 @@ namespace Xeen { const char *const CREDITS = - "\013012\010000\003c\01435Designed and Directed By:\n" - "\01417Jon Van Caneghem\003l\n" + "\013""012\010""000\003""c\014""35Designed and Directed By:\n" + "\014""17Jon Van Caneghem\003""l\n" "\n" - "\t025\01435Programming:\n" - "\t035\01417Mark Caldwell\n" + "\t025\014""35Programming:\n" + "\t035\014""17Mark Caldwell\n" "\t035Dave Hathaway\n" "\n" - "\t025\01435Sound System & FX:\n" - "\t035\01417Mike Heilemann\n" + "\t025\014""35Sound System & FX:\n" + "\t035\014""17Mike Heilemann\n" "\n" - "\t025\01435Music & Speech:\n" - "\t035\01417Tim Tully\n" + "\t025\014""35Music & Speech:\n" + "\t035\014""17Tim Tully\n" "\n" - "\t025\01435Writing:\n" - "\t035\01417Paul Rattner\n" + "\t025\014""35Writing:\n" + "\t035\014""17Paul Rattner\n" "\t035Debbie Van Caneghem\n" - "\t035Jon Van Caneghem\013012\n" + "\t035Jon Van Caneghem\013""012\n" "\n" "\n" - "\t180\01435Graphics:\n" - "\t190\01417Jonathan P. Gwyn\n" + "\t180\014""35Graphics:\n" + "\t190\014""17Jonathan P. Gwyn\n" "\t190Bonita Long-Hemsath\n" "\t190Julia Ulano\n" "\t190Ricardo Barrera\n" "\n" - "\t180\01435Testing:\n" - "\t190\01417Benjamin Bent\n" + "\t180\014""35Testing:\n" + "\t190\014""17Benjamin Bent\n" "\t190Christian Dailey\n" "\t190Mario Escamilla\n" "\t190Marco Hunter\n" "\t190Robert J. Lupo\n" "\t190Clayton Retzer\n" - "\t190David Vela\003c"; + "\t190David Vela\003""c"; const char *const OPTIONS_TITLE = - "\x0D\x01\003c\014dMight and Magic Options\n" + "\x0D\x01\003""c\014""dMight and Magic Options\n" "World of Xeen\x02\n" "\v117Copyright (c) 1993 NWC, Inc.\n" "All Rights Reserved\x01"; -- cgit v1.2.3 From e1404f127d376225d0c15c43b12f59749689c731 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 2 Jan 2015 13:30:00 -1000 Subject: XEEN: Simplified SpriteResource class, char faces loading in main engine --- engines/xeen/events.h | 2 +- engines/xeen/sprites.cpp | 69 ++++++++++++++++++------------------------------ engines/xeen/sprites.h | 44 +++++++----------------------- engines/xeen/xeen.cpp | 31 ++++++++++++++++++++-- engines/xeen/xeen.h | 7 ++++- 5 files changed, 72 insertions(+), 81 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/events.h b/engines/xeen/events.h index 5a9faf14d8..7a6a65f4fb 100644 --- a/engines/xeen/events.h +++ b/engines/xeen/events.h @@ -41,7 +41,7 @@ private: uint32 _gameCounter; uint32 _priorGameCounterTime; Common::KeyCode _keyCode; - FramesResource _sprites; + SpriteResource _sprites; void nextFrame(); public: diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 1b18e98dfd..9485bd28b8 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -29,26 +29,46 @@ namespace Xeen { -GraphicResource::GraphicResource(const Common::String &filename) { +SpriteResource::SpriteResource() { + _filesize = 0; + _data = nullptr; +} + +SpriteResource::SpriteResource(const Common::String &filename) { + _data = nullptr; + load(filename); +} + +void SpriteResource::load(const Common::String &filename) { // Open the resource File f(filename); // Read in a copy of the file _filesize = f.size(); + delete[] _data; _data = new byte[_filesize]; - f.seek(0); f.read(_data, _filesize); + + // Read in the index + f.seek(0); + int count = f.readUint16LE(); + _index.resize(count); + + for (int i = 0; i < count; ++i) { + _index[i]._offset1 = f.readUint16LE(); + _index[i]._offset2 = f.readUint16LE(); + } } -GraphicResource::~GraphicResource() { +SpriteResource::~SpriteResource() { delete[] _data; } -int GraphicResource::size() const { - return READ_LE_UINT16(_data); +int SpriteResource::size() const { + return _index.size(); } -void GraphicResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const { +void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const { // Get cell header Common::MemoryReadStream f(_data, _filesize); f.seek(offset); @@ -151,43 +171,6 @@ void GraphicResource::drawOffset(XSurface &dest, uint16 offset, const Common::Po destPos.x + xOffset + width, destPos.y + yOffset + height)); } -/*------------------------------------------------------------------------*/ - -FramesResource::FramesResource(const Common::String &filename) : - GraphicResource(filename) { - // Read in the index - Common::MemoryReadStream f(_data, _filesize); - int count = f.readUint16LE(); - _index.resize(count); - - for (int i = 0; i < count; ++i) { - _index[i] = f.readUint32LE(); - } -} - -void FramesResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const { - drawOffset(dest, _index[frame], destPos); -} - -void FramesResource::draw(XSurface &dest, int frame) const { - draw(dest, frame, Common::Point()); -} - -/*------------------------------------------------------------------------*/ - -SpriteResource::SpriteResource(const Common::String &filename) : - GraphicResource(filename) { - // Read in the index - Common::MemoryReadStream f(_data, _filesize); - int count = f.readUint16LE(); - _index.resize(count); - - for (int i = 0; i < count; ++i) { - _index[i]._offset1 = f.readUint16LE(); - _index[i]._offset2 = f.readUint16LE(); - } -} - void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const { drawOffset(dest, _index[frame]._offset1, destPos); if (_index[frame]._offset2) diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index 6c01a9ff82..8613d90b29 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -33,53 +33,29 @@ namespace Xeen { class XeenEngine; -class GraphicResource { -protected: - int32 _filesize; - byte *_data; - - void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const; -public: - GraphicResource(const Common::String &filename); - - virtual ~GraphicResource(); - - int size() const; -}; - -/** - * Defines a resource that Contains a list of singular sprite frames - */ -class FramesResource : public GraphicResource { -private: - Common::Array<uint32> _index; -public: - FramesResource(const Common::String &filename); - virtual ~FramesResource() {} - - void draw(XSurface &dest, int frame, const Common::Point &destPos) const; - - void draw(XSurface &dest, int frame) const; -}; - -/** - * Defines a resource that contains sets of two layered sprites per frame - */ -class SpriteResource : public GraphicResource { +class SpriteResource { private: struct IndexEntry { uint16 _offset1, _offset2; }; Common::Array<IndexEntry> _index; + int32 _filesize; + byte *_data; + void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const; public: + SpriteResource(); SpriteResource(const Common::String &filename); - virtual ~SpriteResource() {} + virtual ~SpriteResource(); + + void load(const Common::String &filename); void draw(XSurface &dest, int frame, const Common::Point &destPos) const; void draw(XSurface &dest, int frame) const; + + int size() const; }; } // End of namespace Xeen diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index dfa05b0aa1..f2bbbe0517 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -42,7 +42,10 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _sound = nullptr; _eventData = nullptr; Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr); + Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr); + _isEarlyGame = false; + } XeenEngine::~XeenEngine() { @@ -243,14 +246,14 @@ void XeenEngine::showMainMenu() { void XeenEngine::playGame() { _saves->reset(); - drawUI(); + drawUI(true); } /* * Lots of stuff in this method. * TODO: Consider renaming method when better understood */ -void XeenEngine::drawUI() { +void XeenEngine::drawUI(bool soundPlayed) { SpriteResource sprites1("global.icn"), borderSprites("border.icn"); // Get mappings to the active characters in the party @@ -260,6 +263,30 @@ void XeenEngine::drawUI() { } _isEarlyGame = _party._minutes >= 300; + + if (_party._mazeId == 0) { + if (!soundPlayed) { + warning("TODO: loadSound?"); + } + + if (!_partyFaces[0]) { + // Xeen only uses 24 of possible 30 character slots + loadCharIcons(24); + + for (int i = 0; i < _party._partyCount; ++i) + _partyFaces[i] = &_charFaces[_party._partyMembers[i]]; + } + } +} + +void XeenEngine::loadCharIcons(int numChars) { + for (int i = 0; i < numChars; ++i) { + // Load new character resource + Common::String name = Common::String::format("char%02d.fac", i); + _charFaces[i].load(name); + } + + _dseFace.load("dse.fac"); } } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 787cc3d435..7155e39483 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -81,12 +81,17 @@ private: Common::RandomSource _randomSource; int _loadSaveSlot; bool _isEarlyGame; + SpriteResource _charFaces[TOTAL_CHARACTERS]; + SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; + SpriteResource _dseFace; void showIntro(); void showMainMenu(); - void drawUI(); + void drawUI(bool soundPlayed); + + void loadCharIcons(int numChars); protected: /** * Play the game -- cgit v1.2.3 From 9b40bd5c6aa8110e7b3a13eec2550a4c6f201668 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 2 Jan 2015 15:25:14 -1000 Subject: XEEN: More UI loading code, refactored Dialog base to ButtonContainer --- engines/xeen/dialogs.cpp | 60 +++++++++++++++++++++++++--------------- engines/xeen/dialogs.h | 45 +++++++++++++++++------------- engines/xeen/dialogs_options.cpp | 19 ++++--------- engines/xeen/party.h | 1 + engines/xeen/xeen.cpp | 47 ++++++++++++++++++++++++++----- engines/xeen/xeen.h | 10 +++++-- 6 files changed, 119 insertions(+), 63 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index 4d1a87647d..810c136431 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -22,34 +22,36 @@ #include "common/scummsys.h" #include "xeen/dialogs.h" +#include "xeen/events.h" #include "xeen/resources.h" +#include "xeen/xeen.h" namespace Xeen { /** * Saves the current list of buttons */ -void Dialog::saveButtons() { +void ButtonContainer::saveButtons() { _savedButtons.push(_buttons); } /* * Clears the current list of defined buttons */ -void Dialog::clearButtons() { +void ButtonContainer::clearButtons() { _buttons.clear(); } -void Dialog::restoreButtons() { +void ButtonContainer::restoreButtons() { _buttons = _savedButtons.pop(); } -void Dialog::addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw = true) { - _buttons.push_back(DialogButton(bounds, c, sprites, draw)); +void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw = true) { + _buttons.push_back(UIButton(bounds, val, sprites, draw)); } -void Dialog::checkEvents() { - EventsManager &events = *_vm->_events; +void ButtonContainer::checkEvents(XeenEngine *vm) { + EventsManager &events = *vm->_events; events.pollEventsAndWait(); if (events._leftButton) { @@ -59,7 +61,7 @@ void Dialog::checkEvents() { for (uint i = 0; i < _buttons.size(); ++i) { if (_buttons[i]._bounds.contains(pt)) { - _key = _buttons[i]._c; + _buttonValue = _buttons[i]._value; return; } } @@ -67,7 +69,7 @@ void Dialog::checkEvents() { Common::KeyState keyState; events.getKey(keyState); if (keyState.ascii >= 32 && keyState.ascii <= 127) { - _key = keyState.ascii; + _buttonValue = keyState.ascii; return; } } @@ -77,13 +79,13 @@ void Dialog::checkEvents() { /** * Draws the scroll in the background */ -void Dialog::doScroll(bool drawFlag, bool doFade) { - Screen &screen = *_vm->_screen; - EventsManager &events = *_vm->_events; +void ButtonContainer::doScroll(XeenEngine *vm, bool drawFlag, bool doFade) { + Screen &screen = *vm->_screen; + EventsManager &events = *vm->_events; - if (_vm->getGameID() != GType_Clouds) { + if (vm->getGameID() != GType_Clouds) { if (doFade) { - _vm->_screen->fadeIn(2); + screen.fadeIn(2); } return; } @@ -127,8 +129,8 @@ void Dialog::doScroll(bool drawFlag, bool doFade) { marb[i / 5]->draw(screen, i % 5); } - while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0) - _vm->_events->pollEventsAndWait(); + while (!vm->shouldQuit() && events.timeElapsed() == 0) + events.pollEventsAndWait(); screen._windows[0].update(); if (i == 0 && doFade) @@ -151,8 +153,8 @@ void Dialog::doScroll(bool drawFlag, bool doFade) { marb[i / 5]->draw(screen, i % 5); } - while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0) - _vm->_events->pollEventsAndWait(); + while (!vm->shouldQuit() && events.timeElapsed() == 0) + events.pollEventsAndWait(); screen._windows[0].update(); if (i == 0 && doFade) @@ -178,10 +180,24 @@ void Dialog::doScroll(bool drawFlag, bool doFade) { delete hand[i]; } +/** + * Draws the buttons onto the passed surface + */ +void ButtonContainer::drawButtons(XSurface *surface) { + for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) { + UIButton &btn = _buttons[btnIndex]; + if (btn._draw) { + btn._sprites->draw(*surface, btnIndex * 2, + Common::Point(btn._bounds.left, btn._bounds.top)); + } + } +} + + /*------------------------------------------------------------------------*/ void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) { - checkEvents(); + checkEvents(_vm); } /*------------------------------------------------------------------------*/ @@ -197,12 +213,12 @@ void CreditsScreen::execute() { EventsManager &events = *_vm->_events; // Handle drawing the credits screen - doScroll(true, false); + doScroll(_vm, true, false); screen._windows[28].close(); screen.loadBackground("marb.raw"); screen._windows[0].writeString(CREDITS); - doScroll(false, false); + doScroll(_vm, false, false); events.setCursor(0); screen._windows[0].update(); @@ -212,7 +228,7 @@ void CreditsScreen::execute() { while (!events.isKeyMousePressed()) events.pollEventsAndWait(); - doScroll(true, false); + doScroll(_vm, true, false); } } // End of namespace Xeen diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h index 1f8f2fb624..61ae73473d 100644 --- a/engines/xeen/dialogs.h +++ b/engines/xeen/dialogs.h @@ -26,36 +26,39 @@ #include "common/array.h" #include "common/stack.h" #include "common/rect.h" -#include "xeen/xeen.h" +#include "xeen/sprites.h" namespace Xeen { -class DialogButton { +class XeenEngine; + +class UIButton { public: Common::Rect _bounds; SpriteResource *_sprites; - char _c; + int _value; bool _draw; - DialogButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw) : - _bounds(bounds), _c(c), _sprites(sprites), _draw(draw) {} + UIButton(const Common::Rect &bounds, int value, SpriteResource *sprites, bool draw) : + _bounds(bounds), _value(value), _sprites(sprites), _draw(draw) {} - DialogButton() : _c('\0'), _sprites(nullptr), _draw(false) {} + UIButton() : _value(0), _sprites(nullptr), _draw(false) {} }; -class Dialog { +class ButtonContainer { private: - Common::Stack< Common::Array<DialogButton> > _savedButtons; + Common::Stack< Common::Array<UIButton> > _savedButtons; protected: - XeenEngine *_vm; - Common::Array<DialogButton> _buttons; - char _key; + Common::Array<UIButton> _buttons; + int _buttonValue; - void doScroll(bool drawFlag, bool doFade); + void doScroll(XeenEngine *vm, bool drawFlag, bool doFade); - void checkEvents(); + void checkEvents(XeenEngine *vm); + + void drawButtons(XSurface *surface); public: - Dialog(XeenEngine *vm): _vm(vm), _key('\0') {} + ButtonContainer() : _buttonValue(0) {} void saveButtons(); @@ -63,19 +66,23 @@ public: void restoreButtons(); - void addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw); + void addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw); }; -class SettingsBaseDialog : public Dialog { +class SettingsBaseDialog : public ButtonContainer { protected: + XeenEngine *_vm; + virtual void showContents(SpriteResource &title1, bool mode); public: - SettingsBaseDialog(XeenEngine *vm) : Dialog(vm) {} + SettingsBaseDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} }; -class CreditsScreen: public Dialog { +class CreditsScreen: public ButtonContainer { private: - CreditsScreen(XeenEngine *vm) : Dialog(vm) {} + XeenEngine *_vm; + + CreditsScreen(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} void execute(); public: diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp index e85a4af51d..eace67eecd 100644 --- a/engines/xeen/dialogs_options.cpp +++ b/engines/xeen/dialogs_options.cpp @@ -81,14 +81,14 @@ void OptionsMenu::execute() { while (!_vm->shouldQuit()) { // Show the dialog with a continually animating background - while (!_vm->shouldQuit() && _key == '\0') + while (!_vm->shouldQuit() && !_buttonValue) showContents(title1Sprites, true); if (_vm->shouldQuit()) return; // Handle keypress - char key = toupper(_key); - _key = '\0'; + int key = toupper(_buttonValue); + _buttonValue = 0; if (key == 'C' || key == 'V') { // Show credits @@ -218,20 +218,13 @@ void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) { screen._windows[28].frame(); screen._windows[28].writeString(OPTIONS_TITLE); - for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) { - DialogButton &btn = _buttons[btnIndex]; - if (btn._draw) { - btn._sprites->draw(screen._windows[0], btnIndex * 2, - Common::Point(btn._bounds.left, btn._bounds.top)); - } - } + drawButtons(&screen._windows[0]); if (waitFlag) { screen._windows[0].update(); - while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID && - events.timeElapsed() < 3) { - checkEvents(); + while (!_vm->shouldQuit() && !_buttonValue && events.timeElapsed() < 3) { + checkEvents(_vm); } } } diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 6a6ec5f8a1..9031b8831e 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -57,6 +57,7 @@ enum ConditionType { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, #define ITEMS_COUNT 36 #define TOTAL_CHARACTERS 30 +#define XEEN_TOTAL_CHARACTERS 24 #define MAX_ACTIVE_PARTY 6 class XeenEngine; diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index f2bbbe0517..d7f6138342 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -34,7 +34,7 @@ namespace Xeen { XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) - : _gameDescription(gameDesc), Engine(syst), _randomSource("Xeen") { + : Engine(syst), ButtonContainer(), _gameDescription(gameDesc), _randomSource("Xeen") { _debugger = nullptr; _events = nullptr; _saves = nullptr; @@ -43,9 +43,9 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _eventData = nullptr; Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr); Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr); - _isEarlyGame = false; - + _loadDarkSide = 1; + _buttonsLoaded = false; } XeenEngine::~XeenEngine() { @@ -246,15 +246,16 @@ void XeenEngine::showMainMenu() { void XeenEngine::playGame() { _saves->reset(); - drawUI(true); + setupUI(true); } /* * Lots of stuff in this method. * TODO: Consider renaming method when better understood */ -void XeenEngine::drawUI(bool soundPlayed) { - SpriteResource sprites1("global.icn"), borderSprites("border.icn"); +void XeenEngine::setupUI(bool soundPlayed) { + SpriteResource sprites1("global.icn"), borderSprites("border.icn"), + uiSprites("inn.icn"); // Get mappings to the active characters in the party Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr); @@ -271,11 +272,39 @@ void XeenEngine::drawUI(bool soundPlayed) { if (!_partyFaces[0]) { // Xeen only uses 24 of possible 30 character slots - loadCharIcons(24); + loadCharIcons(XEEN_TOTAL_CHARACTERS); for (int i = 0; i < _party._partyCount; ++i) _partyFaces[i] = &_charFaces[_party._partyMembers[i]]; } + + _mode = MODE_1; + Common::Array<int> xeenSideChars; + + // Build up a list of characters on the same Xeen side being loaded + for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { + PlayerStruct &player = _roster[i]; + if (player._name.empty() || player._xeenSide != _loadDarkSide) + continue; + + xeenSideChars.push_back(i); + } + + // Add in buttons for the UI + _buttonsLoaded = true; + addButton(Common::Rect(16, 100, 40, 120), 242, &uiSprites, true); + addButton(Common::Rect(52, 100, 76, 120), 243, &uiSprites, true); + addButton(Common::Rect(87, 100, 111, 120), 68, &uiSprites, true); + addButton(Common::Rect(122, 100, 146, 120), 82, &uiSprites, true); + addButton(Common::Rect(157, 100, 181, 120), 67, &uiSprites, true); + addButton(Common::Rect(192, 100, 216, 120), 88, &uiSprites, true); + addButton(Common::Rect(), 27, &uiSprites, false); + addButton(Common::Rect(16, 16, 48, 48), 49, &uiSprites, false); + addButton(Common::Rect(117, 16, 139, 48), 50, &uiSprites, false); + addButton(Common::Rect(16, 59, 48, 81), 51, &uiSprites, false); + addButton(Common::Rect(117, 59, 149, 81), 52, &uiSprites, false); + + setupGameBackground(); } } @@ -289,4 +318,8 @@ void XeenEngine::loadCharIcons(int numChars) { _dseFace.load("dse.fac"); } +void XeenEngine::setupGameBackground() { + +} + } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 7155e39483..7261efc879 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -32,6 +32,7 @@ #include "common/util.h" #include "engines/engine.h" #include "xeen/debugger.h" +#include "xeen/dialogs.h" #include "xeen/events.h" #include "xeen/party.h" #include "xeen/saves.h" @@ -67,6 +68,7 @@ enum XeenDebugChannels { enum Mode { MODE_0 = 0, + MODE_1 = 1, MODE_9 = 9 }; @@ -75,23 +77,27 @@ struct XeenGameDescription; #define XEEN_SAVEGAME_VERSION 1 #define GAME_FRAME_TIME 50 -class XeenEngine : public Engine { +class XeenEngine : public Engine, public ButtonContainer { private: const XeenGameDescription *_gameDescription; Common::RandomSource _randomSource; int _loadSaveSlot; bool _isEarlyGame; + int _loadDarkSide; SpriteResource _charFaces[TOTAL_CHARACTERS]; SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; SpriteResource _dseFace; + bool _buttonsLoaded; void showIntro(); void showMainMenu(); - void drawUI(bool soundPlayed); + void setupUI(bool soundPlayed); void loadCharIcons(int numChars); + + void setupGameBackground(); protected: /** * Play the game -- cgit v1.2.3 From 7d4fcfd5afb272c62ad7f1628cc1adfe17c8ee6f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 2 Jan 2015 16:02:24 -1000 Subject: XEEN: Added checkSkill and animating indicators to assembleBorder --- engines/xeen/dialogs.cpp | 2 +- engines/xeen/dialogs_options.cpp | 8 ++--- engines/xeen/party.h | 2 +- engines/xeen/screen.h | 1 + engines/xeen/sprites.cpp | 4 --- engines/xeen/sprites.h | 4 ++- engines/xeen/xeen.cpp | 65 ++++++++++++++++++++++++++++++++++++++-- engines/xeen/xeen.h | 12 ++++++++ 8 files changed, 85 insertions(+), 13 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index 810c136431..70a22d16ee 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -214,7 +214,7 @@ void CreditsScreen::execute() { // Handle drawing the credits screen doScroll(_vm, true, false); - screen._windows[28].close(); + screen._windows[GAME_WINDOW].close(); screen.loadBackground("marb.raw"); screen._windows[0].writeString(CREDITS); diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp index eace67eecd..fb7366c5c7 100644 --- a/engines/xeen/dialogs_options.cpp +++ b/engines/xeen/dialogs_options.cpp @@ -56,7 +56,7 @@ void OptionsMenu::execute() { File newBright("newbrigh.m"); _vm->_sound->playMusic(newBright); - screen._windows[28].setBounds(Common::Rect(72, 25, 248, 175)); + screen._windows[GAME_WINDOW].setBounds(Common::Rect(72, 25, 248, 175)); Common::String title1, title2; startup(title1, title2); @@ -202,7 +202,7 @@ void WorldOptionsMenu::setBackground(bool doFade) { } void WorldOptionsMenu::openWindow() { - _vm->_screen->_windows[28].open(); + _vm->_screen->_windows[GAME_WINDOW].open(); } void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) { @@ -215,8 +215,8 @@ void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) { title1.draw(screen._windows[0], _bgFrame); // Draw the basic frame for the optitons menu and title text - screen._windows[28].frame(); - screen._windows[28].writeString(OPTIONS_TITLE); + screen._windows[GAME_WINDOW].frame(); + screen._windows[GAME_WINDOW].writeString(OPTIONS_TITLE); drawButtons(&screen._windows[0]); diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 9031b8831e..a42fe6ee98 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -50,7 +50,7 @@ enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3, SPOT_DOORS = 16, DANGER_SENSE = 17 }; -enum ConditionType { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, +enum ConditionType { CURSED = 0, HEARTBROKEN = 1, WEAK = 2, POISONED = 3, DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11 }; diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index fd8a50968f..0f16934e6b 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -36,6 +36,7 @@ namespace Xeen { #define SCREEN_HEIGHT 200 #define PALETTE_COUNT 256 #define PALETTE_SIZE (256 * 3) +#define GAME_WINDOW 28 class XeenEngine; class Screen; diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 9485bd28b8..5b8fe5266a 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -64,10 +64,6 @@ SpriteResource::~SpriteResource() { delete[] _data; } -int SpriteResource::size() const { - return _index.size(); -} - void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const { // Get cell header Common::MemoryReadStream f(_data, _filesize); diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index 8613d90b29..e9cdf721eb 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -55,7 +55,9 @@ public: void draw(XSurface &dest, int frame) const; - int size() const; + int size() const { return _index.size(); } + + bool empty() const { return _index.size() == 0; } }; } // End of namespace Xeen diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index d7f6138342..a46526e6ec 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -46,6 +46,11 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _isEarlyGame = false; _loadDarkSide = 1; _buttonsLoaded = false; + _batUIFrame = 0; + _spotDoorsUIFrame = 0; + _spotDoorsAllowed = false; + _dangerSenseUIFrame = 0; + _dangerSenseAllowed = false; } XeenEngine::~XeenEngine() { @@ -254,8 +259,10 @@ void XeenEngine::playGame() { * TODO: Consider renaming method when better understood */ void XeenEngine::setupUI(bool soundPlayed) { - SpriteResource sprites1("global.icn"), borderSprites("border.icn"), - uiSprites("inn.icn"); + SpriteResource uiSprites("inn.icn"); + _globalSprites.load("global.icn"); + _borderSprites.load("border.icn"); + _spellFxSprites.load("spellfx.icn"); // Get mappings to the active characters in the party Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr); @@ -319,7 +326,61 @@ void XeenEngine::loadCharIcons(int numChars) { } void XeenEngine::setupGameBackground() { + _screen->loadBackground("back.raw"); + assembleBorder(); +} + +void XeenEngine::assembleBorder() { + Window &gameWindow = _screen->_windows[28]; + + // Draw the outer frame + _globalSprites.draw(gameWindow, 0); + // Draw the animating bat character used to show when levitate is active + _borderSprites.draw(*_screen, _party._levitateActive ? _batUIFrame + 16 : 16); + _batUIFrame = (_batUIFrame + 1) % 12; + + // Draw UI element to indicate whether can spot hidden doors + _borderSprites.draw(*_screen, + (_spotDoorsAllowed && checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, + Common::Point(194, 91)); + _spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12; + + // Draw UI element to indicate whether can sense danger + _borderSprites.draw(*_screen, + (_dangerSenseAllowed && checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40, + Common::Point(107, 9)); + _dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12; + + + // TODO +} + +bool XeenEngine::checkSkill(Skill skillId) { + int total = 0; + for (int i = 0; i < _party._partyCount; ++i) { + if (_activeRoster[i]->_skills[skillId]) { + ++total; + + switch (skillId) { + case MOUNTAINEER: + case PATHFINDER: + // At least two characters need skill for check to return true + if (total == 2) + return true; + break; + case CRUSADER: + case SWIMMING: + // Entire party must have skill for check to return true + if (total == _party._partyCount) + return true; + break; + default: + // All other skills only need to have a single player having it + return true; + } + } + } } } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 7261efc879..b6ca766088 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -87,7 +87,15 @@ private: SpriteResource _charFaces[TOTAL_CHARACTERS]; SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; SpriteResource _dseFace; + SpriteResource _globalSprites; + SpriteResource _borderSprites; + SpriteResource _spellFxSprites; bool _buttonsLoaded; + int _batUIFrame; + int _spotDoorsUIFrame; + bool _spotDoorsAllowed; + int _dangerSenseUIFrame; + bool _dangerSenseAllowed; void showIntro(); @@ -98,6 +106,10 @@ private: void loadCharIcons(int numChars); void setupGameBackground(); + + void assembleBorder(); + + bool checkSkill(Skill skillId); protected: /** * Play the game -- cgit v1.2.3 From 1a999e3ceb39603bca213f81342a055e1eee7ebe Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 2 Jan 2015 16:08:38 -1000 Subject: XEEN: Refactored checkSkill into Party class --- engines/xeen/party.cpp | 291 +++++++++++++++++++++++++++---------------------- engines/xeen/party.h | 128 +++++++++++----------- engines/xeen/xeen.cpp | 36 +----- engines/xeen/xeen.h | 3 - 4 files changed, 229 insertions(+), 229 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index c5f80eb1f5..97b4a768cd 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -40,138 +40,6 @@ void AttributePair::synchronize(Common::Serializer &s) { /*------------------------------------------------------------------------*/ -Party::Party() { - _partyCount = 0; - _realPartyCount = 0; - Common::fill(&_partyMembers[0], &_partyMembers[8], 0); - _mazeDirection = DIR_NORTH; - _mazeId = _priorMazeId = 0; - _levitateActive = false; - _automapOn = false; - _wizardEyeActive = false; - _clairvoyanceActive = false; - _walkOnWaterActive = false; - _blessedActive = false; - _powerShieldActive = false; - _holyBonusActive = false; - _heroismActive = false; - _difficulty = ADVENTURER; - _cloudsEnd = false; - _darkSideEnd = false; - _worldEnd = false; - hour_maybe = 0; - _day = 0; - _year = 0; - _minutes = 0; - _food = 0; - _lightCount = 0; - _torchCount = 0; - _fireResistence = 0; - _electricityResistence = 0; - _coldResistence = 0; - _poisonResistence = 0; - _deathCount = 0; - _winCount = 0; - _lossCount = 0; - _gold = 0; - _gems = 0; - _bankGold = 0; - _bankGems = 0; - _totalTime = 0; - _rested = false; - - Common::fill(&_gameFlags[0], &_gameFlags[512], false); - Common::fill(&_autoNotes[0], &_autoNotes[128], false); - Common::fill(&_quests[0], &_quests[64], false); - Common::fill(&_questItems[0], &_questItems[85], 0); - - for (int i = 0; i < TOTAL_CHARACTERS; ++i) - Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false); -} - -void Party::synchronize(Common::Serializer &s) { - byte dummy[30]; - Common::fill(&dummy[0], &dummy[30], 0); - - s.syncAsByte(_partyCount); - s.syncAsByte(_realPartyCount); - for (int i = 0; i < 8; ++i) - s.syncAsByte(_partyMembers[i]); - s.syncAsByte(_mazeDirection); - s.syncAsByte(_mazePosition.x); - s.syncAsByte(_mazePosition.y); - s.syncAsByte(_mazeId); - - // Game configuration flags not used in this implementation - s.syncBytes(dummy, 3); - - s.syncAsByte(_priorMazeId); - s.syncAsByte(_levitateActive); - s.syncAsByte(_automapOn); - s.syncAsByte(_wizardEyeActive); - s.syncAsByte(_clairvoyanceActive); - s.syncAsByte(_walkOnWaterActive); - s.syncAsByte(_blessedActive); - s.syncAsByte(_powerShieldActive); - s.syncAsByte(_holyBonusActive); - s.syncAsByte(_heroismActive); - s.syncAsByte(_difficulty); - - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithWeapons[i].synchronize(s); - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithArmor[i].synchronize(s); - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithAccessories[i].synchronize(s); - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithMisc[i].synchronize(s); - - s.syncAsUint16LE(_cloudsEnd); - s.syncAsUint16LE(_darkSideEnd); - s.syncAsUint16LE(_worldEnd); - s.syncAsUint16LE(hour_maybe); - s.syncAsUint16LE(_day); - s.syncAsUint16LE(_year); - s.syncAsUint16LE(_minutes); - s.syncAsUint16LE(_food); - s.syncAsUint16LE(_lightCount); - s.syncAsUint16LE(_torchCount); - s.syncAsUint16LE(_fireResistence); - s.syncAsUint16LE(_electricityResistence); - s.syncAsUint16LE(_coldResistence); - s.syncAsUint16LE(_poisonResistence); - s.syncAsUint16LE(_deathCount); - s.syncAsUint16LE(_winCount); - s.syncAsUint16LE(_lossCount); - s.syncAsUint32LE(_gold); - s.syncAsUint32LE(_gems); - s.syncAsUint32LE(_bankGold); - s.syncAsUint32LE(_bankGems); - s.syncAsUint32LE(_totalTime); - s.syncAsByte(_rested); - SavesManager::syncBitFlags(s, &_gameFlags[0], &_gameFlags[512]); - SavesManager::syncBitFlags(s, &_autoNotes[0], &_autoNotes[128]); - SavesManager::syncBitFlags(s, &_quests[0], &_quests[64]); - - for (int i = 0; i < 85; ++i) - s.syncAsByte(_questItems[i]); - - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithWeapons2[i].synchronize(s); - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithArmor2[i].synchronize(s); - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithAccessories2[i].synchronize(s); - for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithMisc2[i].synchronize(s); - - for (int i = 0; i < TOTAL_CHARACTERS; ++i) - SavesManager::syncBitFlags(s, &_characterFlags[i][0], &_characterFlags[i][24]); - s.syncBytes(&dummy[0], 30); -} - -/*------------------------------------------------------------------------*/ - Conditions::Conditions() { _cursed = 0; _heartBroken = 0; @@ -315,4 +183,163 @@ void Roster::synchronize(Common::Serializer &s) { (*this)[i].synchronize(s); } +/*------------------------------------------------------------------------*/ + +Party::Party() { + _partyCount = 0; + _realPartyCount = 0; + Common::fill(&_partyMembers[0], &_partyMembers[8], 0); + _mazeDirection = DIR_NORTH; + _mazeId = _priorMazeId = 0; + _levitateActive = false; + _automapOn = false; + _wizardEyeActive = false; + _clairvoyanceActive = false; + _walkOnWaterActive = false; + _blessedActive = false; + _powerShieldActive = false; + _holyBonusActive = false; + _heroismActive = false; + _difficulty = ADVENTURER; + _cloudsEnd = false; + _darkSideEnd = false; + _worldEnd = false; + hour_maybe = 0; + _day = 0; + _year = 0; + _minutes = 0; + _food = 0; + _lightCount = 0; + _torchCount = 0; + _fireResistence = 0; + _electricityResistence = 0; + _coldResistence = 0; + _poisonResistence = 0; + _deathCount = 0; + _winCount = 0; + _lossCount = 0; + _gold = 0; + _gems = 0; + _bankGold = 0; + _bankGems = 0; + _totalTime = 0; + _rested = false; + + Common::fill(&_gameFlags[0], &_gameFlags[512], false); + Common::fill(&_autoNotes[0], &_autoNotes[128], false); + Common::fill(&_quests[0], &_quests[64], false); + Common::fill(&_questItems[0], &_questItems[85], 0); + + for (int i = 0; i < TOTAL_CHARACTERS; ++i) + Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false); +} + +void Party::synchronize(Common::Serializer &s) { + byte dummy[30]; + Common::fill(&dummy[0], &dummy[30], 0); + + s.syncAsByte(_partyCount); + s.syncAsByte(_realPartyCount); + for (int i = 0; i < 8; ++i) + s.syncAsByte(_partyMembers[i]); + s.syncAsByte(_mazeDirection); + s.syncAsByte(_mazePosition.x); + s.syncAsByte(_mazePosition.y); + s.syncAsByte(_mazeId); + + // Game configuration flags not used in this implementation + s.syncBytes(dummy, 3); + + s.syncAsByte(_priorMazeId); + s.syncAsByte(_levitateActive); + s.syncAsByte(_automapOn); + s.syncAsByte(_wizardEyeActive); + s.syncAsByte(_clairvoyanceActive); + s.syncAsByte(_walkOnWaterActive); + s.syncAsByte(_blessedActive); + s.syncAsByte(_powerShieldActive); + s.syncAsByte(_holyBonusActive); + s.syncAsByte(_heroismActive); + s.syncAsByte(_difficulty); + + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithWeapons[i].synchronize(s); + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithArmor[i].synchronize(s); + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithAccessories[i].synchronize(s); + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithMisc[i].synchronize(s); + + s.syncAsUint16LE(_cloudsEnd); + s.syncAsUint16LE(_darkSideEnd); + s.syncAsUint16LE(_worldEnd); + s.syncAsUint16LE(hour_maybe); + s.syncAsUint16LE(_day); + s.syncAsUint16LE(_year); + s.syncAsUint16LE(_minutes); + s.syncAsUint16LE(_food); + s.syncAsUint16LE(_lightCount); + s.syncAsUint16LE(_torchCount); + s.syncAsUint16LE(_fireResistence); + s.syncAsUint16LE(_electricityResistence); + s.syncAsUint16LE(_coldResistence); + s.syncAsUint16LE(_poisonResistence); + s.syncAsUint16LE(_deathCount); + s.syncAsUint16LE(_winCount); + s.syncAsUint16LE(_lossCount); + s.syncAsUint32LE(_gold); + s.syncAsUint32LE(_gems); + s.syncAsUint32LE(_bankGold); + s.syncAsUint32LE(_bankGems); + s.syncAsUint32LE(_totalTime); + s.syncAsByte(_rested); + SavesManager::syncBitFlags(s, &_gameFlags[0], &_gameFlags[512]); + SavesManager::syncBitFlags(s, &_autoNotes[0], &_autoNotes[128]); + SavesManager::syncBitFlags(s, &_quests[0], &_quests[64]); + + for (int i = 0; i < 85; ++i) + s.syncAsByte(_questItems[i]); + + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithWeapons2[i].synchronize(s); + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithArmor2[i].synchronize(s); + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithAccessories2[i].synchronize(s); + for (int i = 0; i < ITEMS_COUNT; ++i) + _blacksmithMisc2[i].synchronize(s); + + for (int i = 0; i < TOTAL_CHARACTERS; ++i) + SavesManager::syncBitFlags(s, &_characterFlags[i][0], &_characterFlags[i][24]); + s.syncBytes(&dummy[0], 30); +} + +bool Party::checkSkill(Skill skillId) { + uint total = 0; + for (uint i = 0; i < _activeParty.size(); ++i) { + if (_activeParty[i]->_skills[skillId]) { + ++total; + + switch (skillId) { + case MOUNTAINEER: + case PATHFINDER: + // At least two characters need skill for check to return true + if (total == 2) + return true; + break; + case CRUSADER: + case SWIMMING: + // Entire party must have skill for check to return true + if (total == _activeParty.size()) + return true; + break; + default: + // All other skills only need to have a single player having it + return true; + } + } + } +} + } // End of namespace Xeen diff --git a/engines/xeen/party.h b/engines/xeen/party.h index a42fe6ee98..d52153739d 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -50,7 +50,7 @@ enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3, SPOT_DOORS = 16, DANGER_SENSE = 17 }; -enum ConditionType { CURSED = 0, HEARTBROKEN = 1, WEAK = 2, POISONED = 3, +enum ConditionType { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11 }; @@ -62,67 +62,6 @@ enum ConditionType { CURSED = 0, HEARTBROKEN = 1, WEAK = 2, POISONED = 3, class XeenEngine; -class Party { -public: - int _partyCount; - int _realPartyCount; - int _partyMembers[8]; - Direction _mazeDirection; - Common::Point _mazePosition; - int _mazeId; - int _priorMazeId; - bool _levitateActive; - bool _automapOn; - bool _wizardEyeActive; - bool _clairvoyanceActive; - bool _walkOnWaterActive; - bool _blessedActive; - bool _powerShieldActive; - bool _holyBonusActive; - bool _heroismActive; - Difficulty _difficulty; - XeenItem _blacksmithWeapons[ITEMS_COUNT]; - XeenItem _blacksmithArmor[ITEMS_COUNT]; - XeenItem _blacksmithAccessories[ITEMS_COUNT]; - XeenItem _blacksmithMisc[ITEMS_COUNT]; - bool _cloudsEnd; - bool _darkSideEnd; - bool _worldEnd; - int hour_maybe; - int _day; - int _year; - int _minutes; - int _food; - int _lightCount; - int _torchCount; - int _fireResistence; - int _electricityResistence; - int _coldResistence; - int _poisonResistence; - int _deathCount; - int _winCount; - int _lossCount; - int _gold; - int _gems; - int _bankGold; - int _bankGems; - int _totalTime; - bool _rested; - bool _gameFlags[512]; - bool _autoNotes[128]; - bool _quests[64]; - int _questItems[85]; - XeenItem _blacksmithWeapons2[ITEMS_COUNT]; - XeenItem _blacksmithArmor2[ITEMS_COUNT]; - XeenItem _blacksmithAccessories2[ITEMS_COUNT]; - XeenItem _blacksmithMisc2[ITEMS_COUNT]; - bool _characterFlags[30][24]; -public: - Party(); - - void synchronize(Common::Serializer &s); -}; - class AttributePair { public: int _permanent; @@ -213,6 +152,71 @@ public: void synchronize(Common::Serializer &s); }; +class Party { +public: + int _partyCount; + int _realPartyCount; + int _partyMembers[8]; + Direction _mazeDirection; + Common::Point _mazePosition; + int _mazeId; + int _priorMazeId; + bool _levitateActive; + bool _automapOn; + bool _wizardEyeActive; + bool _clairvoyanceActive; + bool _walkOnWaterActive; + bool _blessedActive; + bool _powerShieldActive; + bool _holyBonusActive; + bool _heroismActive; + Difficulty _difficulty; + XeenItem _blacksmithWeapons[ITEMS_COUNT]; + XeenItem _blacksmithArmor[ITEMS_COUNT]; + XeenItem _blacksmithAccessories[ITEMS_COUNT]; + XeenItem _blacksmithMisc[ITEMS_COUNT]; + bool _cloudsEnd; + bool _darkSideEnd; + bool _worldEnd; + int hour_maybe; + int _day; + int _year; + int _minutes; + int _food; + int _lightCount; + int _torchCount; + int _fireResistence; + int _electricityResistence; + int _coldResistence; + int _poisonResistence; + int _deathCount; + int _winCount; + int _lossCount; + int _gold; + int _gems; + int _bankGold; + int _bankGems; + int _totalTime; + bool _rested; + bool _gameFlags[512]; + bool _autoNotes[128]; + bool _quests[64]; + int _questItems[85]; + XeenItem _blacksmithWeapons2[ITEMS_COUNT]; + XeenItem _blacksmithArmor2[ITEMS_COUNT]; + XeenItem _blacksmithAccessories2[ITEMS_COUNT]; + XeenItem _blacksmithMisc2[ITEMS_COUNT]; + bool _characterFlags[30][24]; +public: + Common::Array<PlayerStruct *> _activeParty; +public: + Party(); + + void synchronize(Common::Serializer &s); + + bool checkSkill(Skill skillId); +}; + } // End of namespace Xeen #endif /* XEEN_PARTY_H */ diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index a46526e6ec..315e5172b7 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -41,7 +41,6 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _screen = nullptr; _sound = nullptr; _eventData = nullptr; - Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr); Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr); _isEarlyGame = false; _loadDarkSide = 1; @@ -265,9 +264,9 @@ void XeenEngine::setupUI(bool soundPlayed) { _spellFxSprites.load("spellfx.icn"); // Get mappings to the active characters in the party - Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr); + _party._activeParty.resize(_party._partyCount); for (int i = 0; i < _party._partyCount; ++i) { - _activeRoster[i] = &_roster[_party._partyMembers[i]]; + _party._activeParty[i] = &_roster[_party._partyMembers[i]]; } _isEarlyGame = _party._minutes >= 300; @@ -342,13 +341,13 @@ void XeenEngine::assembleBorder() { // Draw UI element to indicate whether can spot hidden doors _borderSprites.draw(*_screen, - (_spotDoorsAllowed && checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, + (_spotDoorsAllowed && _party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, Common::Point(194, 91)); _spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12; // Draw UI element to indicate whether can sense danger _borderSprites.draw(*_screen, - (_dangerSenseAllowed && checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40, + (_dangerSenseAllowed && _party.checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40, Common::Point(107, 9)); _dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12; @@ -356,31 +355,4 @@ void XeenEngine::assembleBorder() { // TODO } -bool XeenEngine::checkSkill(Skill skillId) { - int total = 0; - for (int i = 0; i < _party._partyCount; ++i) { - if (_activeRoster[i]->_skills[skillId]) { - ++total; - - switch (skillId) { - case MOUNTAINEER: - case PATHFINDER: - // At least two characters need skill for check to return true - if (total == 2) - return true; - break; - case CRUSADER: - case SWIMMING: - // Entire party must have skill for check to return true - if (total == _party._partyCount) - return true; - break; - default: - // All other skills only need to have a single player having it - return true; - } - } - } -} - } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index b6ca766088..f63f73d434 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -108,8 +108,6 @@ private: void setupGameBackground(); void assembleBorder(); - - bool checkSkill(Skill skillId); protected: /** * Play the game @@ -143,7 +141,6 @@ public: Common::SeekableReadStream *_eventData; Roster _roster; Party _party; - PlayerStruct *_activeRoster[MAX_ACTIVE_PARTY]; public: XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); virtual ~XeenEngine(); -- cgit v1.2.3 From 166676462ae3ed6ddbe186504cf7ecb5f2e55703 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 2 Jan 2015 16:54:59 -1000 Subject: XEEN: Completed assembleGameBorder method --- engines/xeen/resources.cpp | 2 + engines/xeen/resources.h | 2 + engines/xeen/screen.h | 3 +- engines/xeen/xeen.cpp | 99 ++++++++++++++++++++++++++++++++++++++++++++-- engines/xeen/xeen.h | 13 +++++- 5 files changed, 114 insertions(+), 5 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index de0804dc5c..d7d3fccf98 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -232,4 +232,6 @@ const byte TEXT_COLORS[40][4] = { { 0x00, 0xDB, 0xDB, 0xDB }, }; +const char *DIRECTION_TEXT[4] = { "NORTH", "EAST", "SOUTH", "WEST" }; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index d24b1fe4bf..cf4207b814 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -36,6 +36,8 @@ extern const byte SYMBOLS[20][64]; extern const byte TEXT_COLORS[40][4]; +extern const char *DIRECTION_TEXT[4]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 0f16934e6b..d62191e501 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -50,9 +50,10 @@ private: int _border; int _xLo, _xHi; int _ycL, _ycH; - bool _enabled; void open2(); +public: + bool _enabled; public: virtual void addDirtyRect(const Common::Rect &r); public: diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 315e5172b7..ec98a5ffe8 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -30,6 +30,7 @@ #include "xeen/xeen.h" #include "xeen/dialogs_options.h" #include "xeen/files.h" +#include "xeen/resources.h" namespace Xeen { @@ -50,6 +51,15 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _spotDoorsAllowed = false; _dangerSenseUIFrame = 0; _dangerSenseAllowed = false; + _face1UIFrame = 0; + _face1State = 0; + _face2UIFrame = 0; + _face2State = 0; + _blessedUIFrame = 0; + _powerShieldUIFrame = 0; + _holyBonusUIFrame = 0; + _heroismUIFrame = 0; + _noDirectionSense = false; } XeenEngine::~XeenEngine() { @@ -262,6 +272,8 @@ void XeenEngine::setupUI(bool soundPlayed) { _globalSprites.load("global.icn"); _borderSprites.load("border.icn"); _spellFxSprites.load("spellfx.icn"); + _fecpSprites.load("fecp.brd"); + _blessSprites.load("bless.icn"); // Get mappings to the active characters in the party _party._activeParty.resize(_party._partyCount); @@ -326,10 +338,10 @@ void XeenEngine::loadCharIcons(int numChars) { void XeenEngine::setupGameBackground() { _screen->loadBackground("back.raw"); - assembleBorder(); + assembleGameBorder(); } -void XeenEngine::assembleBorder() { +void XeenEngine::assembleGameBorder() { Window &gameWindow = _screen->_windows[28]; // Draw the outer frame @@ -351,8 +363,89 @@ void XeenEngine::assembleBorder() { Common::Point(107, 9)); _dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12; + // Handle the face UI elements for indicating clairvoyance status + _face1UIFrame = (_face1UIFrame + 1) % 4; + if (_face1State == 0) + _face1UIFrame += 4; + else if (_face1State == 2) + _face1UIFrame = 0; + + _face2UIFrame = (_face2UIFrame + 1) % 4 + 12; + if (_face2State == 0) + _face2UIFrame += 252; + else if (_face2State == 2) + _face2UIFrame = 0; + + if (!_party._clairvoyanceActive) { + _face1UIFrame = 0; + _face2UIFrame = 8; + } - // TODO + _borderSprites.draw(*_screen, _face1UIFrame, Common::Point(0, 32)); + _borderSprites.draw(*_screen, + _screen->_windows[10]._enabled || _screen->_windows[2]._enabled ? + 52 : _face2UIFrame, + Common::Point(215, 32)); + + // Draw resistence indicators + if (!_screen->_windows[10]._enabled && !_screen->_windows[2]._enabled + && _screen->_windows[38]._enabled) { + _fecpSprites.draw(*_screen, _party._fireResistence ? 1 : 0, + Common::Point(2, 2)); + _fecpSprites.draw(*_screen, _party._electricityResistence ? 3 : 2, + Common::Point(219, 2)); + _fecpSprites.draw(*_screen, _party._coldResistence ? 5 : 4, + Common::Point(2, 134)); + _fecpSprites.draw(*_screen, _party._poisonResistence ? 7 : 6, + Common::Point(219, 134)); + } else { + _fecpSprites.draw(*_screen, _party._fireResistence ? 9 : 8, + Common::Point(8, 8)); + _fecpSprites.draw(*_screen, _party._electricityResistence ? 10 : 11, + Common::Point(219, 8)); + _fecpSprites.draw(*_screen, _party._coldResistence ? 12 : 13, + Common::Point(8, 134)); + _fecpSprites.draw(*_screen, _party._poisonResistence ? 14 : 15, + Common::Point(219, 134)); + } + + // Draw UI element for blessed + _blessSprites.draw(*_screen, 16, Common::Point(33, 137)); + if (_party._blessedActive) { + _blessedUIFrame = (_blessedUIFrame + 1) % 4; + _blessSprites.draw(*_screen, _blessedUIFrame, Common::Point(33, 137)); + } + + // Draw UI element for power shield + if (_party._powerShieldActive) { + _powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4; + _blessSprites.draw(*_screen, _powerShieldUIFrame + 4, + Common::Point(55, 137)); + } + + // Draw UI element for holy bonus + if (_party._holyBonusActive) { + _holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4; + _blessSprites.draw(*_screen, _holyBonusUIFrame + 8, Common::Point(160, 137)); + } + + // Draw UI element for heroism + if (_party._heroismActive) { + _heroismUIFrame = (_heroismUIFrame + 1) % 4; + _blessSprites.draw(*_screen, _heroismUIFrame + 12, Common::Point(182, 137)); + } + + // Draw direction character if direction sense is active + if (_party.checkSkill(DIRECTION_SENSE) && !_noDirectionSense) { + const char *dirText = DIRECTION_TEXT[_party._mazeDirection]; + Common::String msg = Common::String::format( + "\002""08\003""c\013""139\011""116%c\014""d\001", *dirText); + _screen->_windows[0].writeString(msg); + } + + // Draw view frame + if (_screen->_windows[12]._enabled) + _screen->_windows[12].frame(); } } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index f63f73d434..c175048389 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -90,12 +90,23 @@ private: SpriteResource _globalSprites; SpriteResource _borderSprites; SpriteResource _spellFxSprites; + SpriteResource _fecpSprites; + SpriteResource _blessSprites; bool _buttonsLoaded; int _batUIFrame; int _spotDoorsUIFrame; bool _spotDoorsAllowed; int _dangerSenseUIFrame; bool _dangerSenseAllowed; + int _face1UIFrame; + bool _face1State; + int _face2UIFrame; + bool _face2State; + int _blessedUIFrame; + int _powerShieldUIFrame; + int _holyBonusUIFrame; + int _heroismUIFrame; + bool _noDirectionSense; void showIntro(); @@ -107,7 +118,7 @@ private: void setupGameBackground(); - void assembleBorder(); + void assembleGameBorder(); protected: /** * Play the game -- cgit v1.2.3 From 97cd5a7e6961be52d545e3c131a85cd90c582441 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 3 Jan 2015 03:19:14 -1000 Subject: XEEN: Split game interface code into it's own class --- engines/xeen/interface.cpp | 231 +++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/interface.h | 73 ++++++++++++++ engines/xeen/module.mk | 1 + engines/xeen/xeen.cpp | 204 +-------------------------------------- engines/xeen/xeen.h | 43 ++------- 5 files changed, 319 insertions(+), 233 deletions(-) create mode 100644 engines/xeen/interface.cpp create mode 100644 engines/xeen/interface.h (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp new file mode 100644 index 0000000000..cdb9204537 --- /dev/null +++ b/engines/xeen/interface.cpp @@ -0,0 +1,231 @@ +/* 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 "xeen/interface.h" +#include "xeen/resources.h" +#include "xeen/xeen.h" + +namespace Xeen { + +Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { + Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr); + _batUIFrame = 0; + _spotDoorsUIFrame = 0; + _dangerSenseUIFrame = 0; + _face1UIFrame = 0; + _face2UIFrame = 0; + _blessedUIFrame = 0; + _powerShieldUIFrame = 0; + _holyBonusUIFrame = 0; + _heroismUIFrame = 0; + _isEarlyGame = false; + _buttonsLoaded = false; + + loadSprites(); +} + +void Interface::loadSprites() { + _globalSprites.load("global.icn"); + _borderSprites.load("border.icn"); + _spellFxSprites.load("spellfx.icn"); + _fecpSprites.load("fecp.brd"); + _blessSprites.load("bless.icn"); +} + +void Interface::setup(bool soundPlayed) { + SpriteResource uiSprites("inn.icn"); + + // Get mappings to the active characters in the party + _vm->_party._activeParty.resize(_vm->_party._partyCount); + for (int i = 0; i < _vm->_party._partyCount; ++i) { + _vm->_party._activeParty[i] = &_vm->_roster[_vm->_party._partyMembers[i]]; + } + + _isEarlyGame = _vm->_party._minutes >= 300; + + if (_vm->_party._mazeId == 0) { + if (!soundPlayed) { + warning("TODO: loadSound?"); + } + + if (!_partyFaces[0]) { + // Xeen only uses 24 of possible 30 character slots + loadCharIcons(XEEN_TOTAL_CHARACTERS); + + for (int i = 0; i < _vm->_party._partyCount; ++i) + _partyFaces[i] = &_charFaces[_vm->_party._partyMembers[i]]; + } + + _vm->_mode = MODE_1; + Common::Array<int> xeenSideChars; + + // Build up a list of characters on the same Xeen side being loaded + for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { + PlayerStruct &player = _vm->_roster[i]; + if (player._name.empty() || player._xeenSide != _vm->_loadDarkSide) + continue; + + xeenSideChars.push_back(i); + } + + // Add in buttons for the UI + _buttonsLoaded = true; + addButton(Common::Rect(16, 100, 40, 120), 242, &uiSprites, true); + addButton(Common::Rect(52, 100, 76, 120), 243, &uiSprites, true); + addButton(Common::Rect(87, 100, 111, 120), 68, &uiSprites, true); + addButton(Common::Rect(122, 100, 146, 120), 82, &uiSprites, true); + addButton(Common::Rect(157, 100, 181, 120), 67, &uiSprites, true); + addButton(Common::Rect(192, 100, 216, 120), 88, &uiSprites, true); + addButton(Common::Rect(), 27, &uiSprites, false); + addButton(Common::Rect(16, 16, 48, 48), 49, &uiSprites, false); + addButton(Common::Rect(117, 16, 139, 48), 50, &uiSprites, false); + addButton(Common::Rect(16, 59, 48, 81), 51, &uiSprites, false); + addButton(Common::Rect(117, 59, 149, 81), 52, &uiSprites, false); + + setupBackground(); + } +} + +void Interface::loadCharIcons(int numChars) { + for (int i = 0; i < numChars; ++i) { + // Load new character resource + Common::String name = Common::String::format("char%02d.fac", i); + _charFaces[i].load(name); + } + + _dseFace.load("dse.fac"); +} + +void Interface::setupBackground() { + _vm->_screen->loadBackground("back.raw"); + assembleBorder(); +} + +void Interface::assembleBorder() { + Screen &screen = *_vm->_screen; + Window &gameWindow = screen._windows[28]; + + // Draw the outer frame + _globalSprites.draw(gameWindow, 0); + + // Draw the animating bat character used to show when levitate is active + _borderSprites.draw(screen, _vm->_party._levitateActive ? _batUIFrame + 16 : 16); + _batUIFrame = (_batUIFrame + 1) % 12; + + // Draw UI element to indicate whether can spot hidden doors + _borderSprites.draw(screen, + (_vm->_spotDoorsAllowed && _vm->_party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, + Common::Point(194, 91)); + _spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12; + + // Draw UI element to indicate whether can sense danger + _borderSprites.draw(screen, + (_vm->_dangerSenseAllowed && _vm->_party.checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40, + Common::Point(107, 9)); + _dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12; + + // Handle the face UI elements for indicating clairvoyance status + _face1UIFrame = (_face1UIFrame + 1) % 4; + if (_vm->_face1State == 0) + _face1UIFrame += 4; + else if (_vm->_face1State == 2) + _face1UIFrame = 0; + + _face2UIFrame = (_face2UIFrame + 1) % 4 + 12; + if (_vm->_face2State == 0) + _face2UIFrame += 252; + else if (_vm->_face2State == 2) + _face2UIFrame = 0; + + if (!_vm->_party._clairvoyanceActive) { + _face1UIFrame = 0; + _face2UIFrame = 8; + } + + _borderSprites.draw(screen, _face1UIFrame, Common::Point(0, 32)); + _borderSprites.draw(screen, + screen._windows[10]._enabled || screen._windows[2]._enabled ? + 52 : _face2UIFrame, + Common::Point(215, 32)); + + // Draw resistence indicators + if (!screen._windows[10]._enabled && !screen._windows[2]._enabled + && screen._windows[38]._enabled) { + _fecpSprites.draw(screen, _vm->_party._fireResistence ? 1 : 0, + Common::Point(2, 2)); + _fecpSprites.draw(screen, _vm->_party._electricityResistence ? 3 : 2, + Common::Point(219, 2)); + _fecpSprites.draw(screen, _vm->_party._coldResistence ? 5 : 4, + Common::Point(2, 134)); + _fecpSprites.draw(screen, _vm->_party._poisonResistence ? 7 : 6, + Common::Point(219, 134)); + } else { + _fecpSprites.draw(screen, _vm->_party._fireResistence ? 9 : 8, + Common::Point(8, 8)); + _fecpSprites.draw(screen, _vm->_party._electricityResistence ? 10 : 11, + Common::Point(219, 8)); + _fecpSprites.draw(screen, _vm->_party._coldResistence ? 12 : 13, + Common::Point(8, 134)); + _fecpSprites.draw(screen, _vm->_party._poisonResistence ? 14 : 15, + Common::Point(219, 134)); + } + + // Draw UI element for blessed + _blessSprites.draw(screen, 16, Common::Point(33, 137)); + if (_vm->_party._blessedActive) { + _blessedUIFrame = (_blessedUIFrame + 1) % 4; + _blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137)); + } + + // Draw UI element for power shield + if (_vm->_party._powerShieldActive) { + _powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4; + _blessSprites.draw(screen, _powerShieldUIFrame + 4, + Common::Point(55, 137)); + } + + // Draw UI element for holy bonus + if (_vm->_party._holyBonusActive) { + _holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4; + _blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137)); + } + + // Draw UI element for heroism + if (_vm->_party._heroismActive) { + _heroismUIFrame = (_heroismUIFrame + 1) % 4; + _blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137)); + } + + // Draw direction character if direction sense is active + if (_vm->_party.checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) { + const char *dirText = DIRECTION_TEXT[_vm->_party._mazeDirection]; + Common::String msg = Common::String::format( + "\002""08\003""c\013""139\011""116%c\014""d\001", *dirText); + screen._windows[0].writeString(msg); + } + + // Draw view frame + if (screen._windows[12]._enabled) + screen._windows[12].frame(); +} + +} // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h new file mode 100644 index 0000000000..565fe84273 --- /dev/null +++ b/engines/xeen/interface.h @@ -0,0 +1,73 @@ +/* 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 XEEN_INTERFACE_H +#define XEEN_INTERFACE_H + +#include "common/scummsys.h" +#include "xeen/dialogs.h" +#include "xeen/party.h" + +namespace Xeen { + +class XeenEngine; + +class Interface: public ButtonContainer { +private: + XeenEngine *_vm; + SpriteResource _dseFace; + SpriteResource _globalSprites; + SpriteResource _borderSprites; + SpriteResource _spellFxSprites; + SpriteResource _fecpSprites; + SpriteResource _blessSprites; + SpriteResource _charFaces[TOTAL_CHARACTERS]; + SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; + + int _batUIFrame; + int _spotDoorsUIFrame; + int _dangerSenseUIFrame; + int _face1UIFrame; + int _face2UIFrame; + int _blessedUIFrame; + int _powerShieldUIFrame; + int _holyBonusUIFrame; + int _heroismUIFrame; + bool _isEarlyGame; + bool _buttonsLoaded; + + void loadSprites(); + + void loadCharIcons(int numChars); + + void assembleBorder(); + + void setupBackground(); +public: + Interface(XeenEngine *vm); + + void setup(bool soundPlayed); +}; + +} // End of namespace Xeen + +#endif /* XEEN_INTERFACE_H */ diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 752608a136..7f0caf7b10 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -11,6 +11,7 @@ MODULE_OBJS := \ events.o \ files.o \ font.o \ + interface.o \ items.o \ party.o \ resdata.o \ diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index ec98a5ffe8..1574871c25 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -35,36 +35,26 @@ namespace Xeen { XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) - : Engine(syst), ButtonContainer(), _gameDescription(gameDesc), _randomSource("Xeen") { + : Engine(syst), _gameDescription(gameDesc), _randomSource("Xeen") { _debugger = nullptr; _events = nullptr; + _interface = nullptr; _saves = nullptr; _screen = nullptr; _sound = nullptr; _eventData = nullptr; - Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr); - _isEarlyGame = false; _loadDarkSide = 1; - _buttonsLoaded = false; - _batUIFrame = 0; - _spotDoorsUIFrame = 0; _spotDoorsAllowed = false; - _dangerSenseUIFrame = 0; _dangerSenseAllowed = false; - _face1UIFrame = 0; _face1State = 0; - _face2UIFrame = 0; _face2State = 0; - _blessedUIFrame = 0; - _powerShieldUIFrame = 0; - _holyBonusUIFrame = 0; - _heroismUIFrame = 0; _noDirectionSense = false; } XeenEngine::~XeenEngine() { delete _debugger; delete _events; + delete _interface; delete _saves; delete _screen; delete _sound; @@ -82,6 +72,7 @@ void XeenEngine::initialize() { FileManager::init(this); _debugger = new Debugger(this); _events = new EventsManager(this); + _interface = new Interface(this); _saves = new SavesManager(this, _party, _roster); _screen = new Screen(this); _screen->setupWindows(); @@ -260,192 +251,7 @@ void XeenEngine::showMainMenu() { void XeenEngine::playGame() { _saves->reset(); - setupUI(true); -} - -/* - * Lots of stuff in this method. - * TODO: Consider renaming method when better understood - */ -void XeenEngine::setupUI(bool soundPlayed) { - SpriteResource uiSprites("inn.icn"); - _globalSprites.load("global.icn"); - _borderSprites.load("border.icn"); - _spellFxSprites.load("spellfx.icn"); - _fecpSprites.load("fecp.brd"); - _blessSprites.load("bless.icn"); - - // Get mappings to the active characters in the party - _party._activeParty.resize(_party._partyCount); - for (int i = 0; i < _party._partyCount; ++i) { - _party._activeParty[i] = &_roster[_party._partyMembers[i]]; - } - - _isEarlyGame = _party._minutes >= 300; - - if (_party._mazeId == 0) { - if (!soundPlayed) { - warning("TODO: loadSound?"); - } - - if (!_partyFaces[0]) { - // Xeen only uses 24 of possible 30 character slots - loadCharIcons(XEEN_TOTAL_CHARACTERS); - - for (int i = 0; i < _party._partyCount; ++i) - _partyFaces[i] = &_charFaces[_party._partyMembers[i]]; - } - - _mode = MODE_1; - Common::Array<int> xeenSideChars; - - // Build up a list of characters on the same Xeen side being loaded - for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { - PlayerStruct &player = _roster[i]; - if (player._name.empty() || player._xeenSide != _loadDarkSide) - continue; - - xeenSideChars.push_back(i); - } - - // Add in buttons for the UI - _buttonsLoaded = true; - addButton(Common::Rect(16, 100, 40, 120), 242, &uiSprites, true); - addButton(Common::Rect(52, 100, 76, 120), 243, &uiSprites, true); - addButton(Common::Rect(87, 100, 111, 120), 68, &uiSprites, true); - addButton(Common::Rect(122, 100, 146, 120), 82, &uiSprites, true); - addButton(Common::Rect(157, 100, 181, 120), 67, &uiSprites, true); - addButton(Common::Rect(192, 100, 216, 120), 88, &uiSprites, true); - addButton(Common::Rect(), 27, &uiSprites, false); - addButton(Common::Rect(16, 16, 48, 48), 49, &uiSprites, false); - addButton(Common::Rect(117, 16, 139, 48), 50, &uiSprites, false); - addButton(Common::Rect(16, 59, 48, 81), 51, &uiSprites, false); - addButton(Common::Rect(117, 59, 149, 81), 52, &uiSprites, false); - - setupGameBackground(); - } -} - -void XeenEngine::loadCharIcons(int numChars) { - for (int i = 0; i < numChars; ++i) { - // Load new character resource - Common::String name = Common::String::format("char%02d.fac", i); - _charFaces[i].load(name); - } - - _dseFace.load("dse.fac"); -} - -void XeenEngine::setupGameBackground() { - _screen->loadBackground("back.raw"); - assembleGameBorder(); -} - -void XeenEngine::assembleGameBorder() { - Window &gameWindow = _screen->_windows[28]; - - // Draw the outer frame - _globalSprites.draw(gameWindow, 0); - - // Draw the animating bat character used to show when levitate is active - _borderSprites.draw(*_screen, _party._levitateActive ? _batUIFrame + 16 : 16); - _batUIFrame = (_batUIFrame + 1) % 12; - - // Draw UI element to indicate whether can spot hidden doors - _borderSprites.draw(*_screen, - (_spotDoorsAllowed && _party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, - Common::Point(194, 91)); - _spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12; - - // Draw UI element to indicate whether can sense danger - _borderSprites.draw(*_screen, - (_dangerSenseAllowed && _party.checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40, - Common::Point(107, 9)); - _dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12; - - // Handle the face UI elements for indicating clairvoyance status - _face1UIFrame = (_face1UIFrame + 1) % 4; - if (_face1State == 0) - _face1UIFrame += 4; - else if (_face1State == 2) - _face1UIFrame = 0; - - _face2UIFrame = (_face2UIFrame + 1) % 4 + 12; - if (_face2State == 0) - _face2UIFrame += 252; - else if (_face2State == 2) - _face2UIFrame = 0; - - if (!_party._clairvoyanceActive) { - _face1UIFrame = 0; - _face2UIFrame = 8; - } - - _borderSprites.draw(*_screen, _face1UIFrame, Common::Point(0, 32)); - _borderSprites.draw(*_screen, - _screen->_windows[10]._enabled || _screen->_windows[2]._enabled ? - 52 : _face2UIFrame, - Common::Point(215, 32)); - - // Draw resistence indicators - if (!_screen->_windows[10]._enabled && !_screen->_windows[2]._enabled - && _screen->_windows[38]._enabled) { - _fecpSprites.draw(*_screen, _party._fireResistence ? 1 : 0, - Common::Point(2, 2)); - _fecpSprites.draw(*_screen, _party._electricityResistence ? 3 : 2, - Common::Point(219, 2)); - _fecpSprites.draw(*_screen, _party._coldResistence ? 5 : 4, - Common::Point(2, 134)); - _fecpSprites.draw(*_screen, _party._poisonResistence ? 7 : 6, - Common::Point(219, 134)); - } else { - _fecpSprites.draw(*_screen, _party._fireResistence ? 9 : 8, - Common::Point(8, 8)); - _fecpSprites.draw(*_screen, _party._electricityResistence ? 10 : 11, - Common::Point(219, 8)); - _fecpSprites.draw(*_screen, _party._coldResistence ? 12 : 13, - Common::Point(8, 134)); - _fecpSprites.draw(*_screen, _party._poisonResistence ? 14 : 15, - Common::Point(219, 134)); - } - - // Draw UI element for blessed - _blessSprites.draw(*_screen, 16, Common::Point(33, 137)); - if (_party._blessedActive) { - _blessedUIFrame = (_blessedUIFrame + 1) % 4; - _blessSprites.draw(*_screen, _blessedUIFrame, Common::Point(33, 137)); - } - - // Draw UI element for power shield - if (_party._powerShieldActive) { - _powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4; - _blessSprites.draw(*_screen, _powerShieldUIFrame + 4, - Common::Point(55, 137)); - } - - // Draw UI element for holy bonus - if (_party._holyBonusActive) { - _holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4; - _blessSprites.draw(*_screen, _holyBonusUIFrame + 8, Common::Point(160, 137)); - } - - // Draw UI element for heroism - if (_party._heroismActive) { - _heroismUIFrame = (_heroismUIFrame + 1) % 4; - _blessSprites.draw(*_screen, _heroismUIFrame + 12, Common::Point(182, 137)); - } - - // Draw direction character if direction sense is active - if (_party.checkSkill(DIRECTION_SENSE) && !_noDirectionSense) { - const char *dirText = DIRECTION_TEXT[_party._mazeDirection]; - Common::String msg = Common::String::format( - "\002""08\003""c\013""139\011""116%c\014""d\001", *dirText); - _screen->_windows[0].writeString(msg); - } - - // Draw view frame - if (_screen->_windows[12]._enabled) - _screen->_windows[12].frame(); + _interface->setup(true); } } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index c175048389..a549c15df4 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -34,6 +34,7 @@ #include "xeen/debugger.h" #include "xeen/dialogs.h" #include "xeen/events.h" +#include "xeen/interface.h" #include "xeen/party.h" #include "xeen/saves.h" #include "xeen/screen.h" @@ -77,48 +78,15 @@ struct XeenGameDescription; #define XEEN_SAVEGAME_VERSION 1 #define GAME_FRAME_TIME 50 -class XeenEngine : public Engine, public ButtonContainer { +class XeenEngine : public Engine { private: const XeenGameDescription *_gameDescription; Common::RandomSource _randomSource; int _loadSaveSlot; - bool _isEarlyGame; - int _loadDarkSide; - SpriteResource _charFaces[TOTAL_CHARACTERS]; - SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; - SpriteResource _dseFace; - SpriteResource _globalSprites; - SpriteResource _borderSprites; - SpriteResource _spellFxSprites; - SpriteResource _fecpSprites; - SpriteResource _blessSprites; - bool _buttonsLoaded; - int _batUIFrame; - int _spotDoorsUIFrame; - bool _spotDoorsAllowed; - int _dangerSenseUIFrame; - bool _dangerSenseAllowed; - int _face1UIFrame; - bool _face1State; - int _face2UIFrame; - bool _face2State; - int _blessedUIFrame; - int _powerShieldUIFrame; - int _holyBonusUIFrame; - int _heroismUIFrame; - bool _noDirectionSense; void showIntro(); void showMainMenu(); - - void setupUI(bool soundPlayed); - - void loadCharIcons(int numChars); - - void setupGameBackground(); - - void assembleGameBorder(); protected: /** * Play the game @@ -144,6 +112,7 @@ private: public: Debugger *_debugger; EventsManager *_events; + Interface *_interface; SavesManager *_saves; Screen *_screen; SoundManager *_sound; @@ -152,6 +121,12 @@ public: Common::SeekableReadStream *_eventData; Roster _roster; Party _party; + int _loadDarkSide; + bool _spotDoorsAllowed; + bool _dangerSenseAllowed; + int _face1State; + int _face2State; + bool _noDirectionSense; public: XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); virtual ~XeenEngine(); -- cgit v1.2.3 From f9316bf14107c3ac46bd8bb53da9665c3652c381 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 3 Jan 2015 19:08:30 -0500 Subject: XEEN: Implemented charIconsPrint --- engines/xeen/interface.cpp | 115 +++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/interface.h | 11 +++++ engines/xeen/party.cpp | 75 ++++++++++++++--------------- engines/xeen/party.h | 42 +++++++---------- engines/xeen/resources.cpp | 47 +++++++++++++++++- engines/xeen/resources.h | 22 ++++++++- engines/xeen/screen.cpp | 16 +++++++ engines/xeen/screen.h | 19 +++++++- engines/xeen/xeen.h | 7 +++ 9 files changed, 284 insertions(+), 70 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index cdb9204537..3a07cecec6 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -39,6 +39,13 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { _heroismUIFrame = 0; _isEarlyGame = false; _buttonsLoaded = false; + _hiliteChar = -1; + Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); + + _faceDrawStructs[0] = DrawStruct(nullptr, 0, 0, 0); + _faceDrawStructs[1] = DrawStruct(nullptr, 0, 101, 0); + _faceDrawStructs[2] = DrawStruct(nullptr, 0, 0, 43); + _faceDrawStructs[3] = DrawStruct(nullptr, 0, 101, 43); loadSprites(); } @@ -49,9 +56,12 @@ void Interface::loadSprites() { _spellFxSprites.load("spellfx.icn"); _fecpSprites.load("fecp.brd"); _blessSprites.load("bless.icn"); + _restoreSprites.load("restorex.icn"); + _hpSprites.load("hpbars.icn"); } void Interface::setup(bool soundPlayed) { + Screen &screen = *_vm->_screen; SpriteResource uiSprites("inn.icn"); // Get mappings to the active characters in the party @@ -88,6 +98,7 @@ void Interface::setup(bool soundPlayed) { } // Add in buttons for the UI + _interfaceText = ""; _buttonsLoaded = true; addButton(Common::Rect(16, 100, 40, 120), 242, &uiSprites, true); addButton(Common::Rect(52, 100, 76, 120), 243, &uiSprites, true); @@ -102,6 +113,11 @@ void Interface::setup(bool soundPlayed) { addButton(Common::Rect(117, 59, 149, 81), 52, &uiSprites, false); setupBackground(); + screen._windows[11].open(); + setupFaces(0, xeenSideChars, 0); + screen._windows[11].writeString(_interfaceText); + + // TODO } } @@ -228,4 +244,103 @@ void Interface::assembleBorder() { screen._windows[12].frame(); } +void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, int v3) { + Common::String playerNames[4]; + Common::String playerRaces[4]; + Common::String playerSex[4]; + Common::String playerClass[4]; + int posIndex; + int charId; + + for (posIndex = 0; posIndex < 4; ++posIndex) { + int charId = xeenSideChars[charIndex]; + bool isInParty = _vm->_party.isInParty(charId); + + if (charId == 0xff) { + while ((int)_buttons.size() > (7 + posIndex)) + _buttons.remove_at(_buttons.size() - 1); + break; + } + + Common::Rect &b = _buttons[7 + posIndex]._bounds; + b.moveTo((posIndex & 1) ? 117 : 16, b.top); + PlayerStruct &ps = _vm->_roster[xeenSideChars[charIndex + posIndex]]; + playerNames[posIndex] = isInParty ? IN_PARTY : ps._name; + playerRaces[posIndex] = RACE_NAMES[ps._race]; + playerSex[posIndex] = SEX_NAMES[ps._sex]; + playerClass[posIndex] = CLASS_NAMES[ps._class]; + } + + charIconsPrint(v3); + + // Set up the sprite set to use for each face + charId = xeenSideChars[charIndex]; + _faceDrawStructs[0]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId]; + charId = xeenSideChars[charIndex + 1]; + _faceDrawStructs[1]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId]; + charId = xeenSideChars[charIndex + 2]; + _faceDrawStructs[2]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId]; + charId = xeenSideChars[charIndex + 3]; + _faceDrawStructs[3]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId]; + + _interfaceText = Common::String::format(PARTY_DETAILS, + playerNames[0].c_str(), playerRaces[0].c_str(), playerSex[0].c_str(), playerClass[0].c_str(), + playerNames[1].c_str(), playerRaces[1].c_str(), playerSex[1].c_str(), playerClass[1].c_str(), + playerNames[2].c_str(), playerRaces[2].c_str(), playerSex[2].c_str(), playerClass[2].c_str(), + playerNames[3].c_str(), playerRaces[3].c_str(), playerSex[3].c_str(), playerClass[3].c_str() + ); +} + +void Interface::charIconsPrint(bool updateFlag) { + Screen &screen = *_vm->_screen; + bool stateFlag = _vm->_mode == MODE_2; + _restoreSprites.draw(screen, 0, Common::Point(8, 149)); + + // Handle drawing the party faces + for (int idx = 0; idx < (stateFlag ? _vm->_party._combatPartyCount : + _vm->_party._partyCount); ++idx) { + int charIndex = stateFlag ? _combatCharIds[idx] : idx; + PlayerStruct &ps = *_vm->_party._activeParty[charIndex]; + Condition charCondition = ps.findCondition(); + int charFrame = FACE_CONDITION_FRAMES[charCondition]; + + SpriteResource *sprites = (charFrame > 4 && !_charFaces[0].empty()) ? + &_dseFace : _partyFaces[charIndex]; + if (charFrame > 4) + charFrame -= 5; + + sprites->draw(screen, charFrame, Common::Point(CHAR_FACES_X[idx], 150)); + } + + if (!_hpSprites.empty()) { + for (int idx = 0; idx < (stateFlag ? _vm->_party._combatPartyCount : + _vm->_party._partyCount); ++idx) { + int charIndex = stateFlag ? _combatCharIds[idx] : idx; + PlayerStruct &ps = *_vm->_party._activeParty[charIndex]; + + // Draw the Hp bar + int maxHp = ps.getMaxHp(); + int frame; + if (ps._currentHp < 1) + frame = 4; + else if (ps._currentHp > maxHp) + frame = 3; + else if (ps._currentHp == maxHp) + frame = 0; + else if (ps._currentHp < (maxHp / 4)) + frame = 2; + else + frame = 1; + + _hpSprites.draw(screen, frame, Common::Point(HP_BARS_X[idx], 182)); + } + } + + if (_hiliteChar != -1) + _globalSprites.draw(screen, 8, Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149)); + + if (updateFlag) + screen._windows[33].update(); +} + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 565fe84273..3ceb08239e 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "xeen/dialogs.h" #include "xeen/party.h" +#include "xeen/screen.h" namespace Xeen { @@ -40,8 +41,12 @@ private: SpriteResource _spellFxSprites; SpriteResource _fecpSprites; SpriteResource _blessSprites; + SpriteResource _restoreSprites; + SpriteResource _hpSprites; SpriteResource _charFaces[TOTAL_CHARACTERS]; SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; + DrawStruct _faceDrawStructs[4]; + int _combatCharIds[8]; int _batUIFrame; int _spotDoorsUIFrame; @@ -54,6 +59,8 @@ private: int _heroismUIFrame; bool _isEarlyGame; bool _buttonsLoaded; + Common::String _interfaceText; + int _hiliteChar; void loadSprites(); @@ -62,6 +69,10 @@ private: void assembleBorder(); void setupBackground(); + + void setupFaces(int charIndex, Common::Array<int> xeenSideChars, int v3); + + void charIconsPrint(bool updateFlag); public: Interface(XeenEngine *vm); diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 97b4a768cd..25366d52ed 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -40,46 +40,6 @@ void AttributePair::synchronize(Common::Serializer &s) { /*------------------------------------------------------------------------*/ -Conditions::Conditions() { - _cursed = 0; - _heartBroken = 0; - _weak = 0; - _poisoned = 0; - _diseased = 0; - _insane = 0; - _inLove = 0; - _drunk = 0; - _asleep = 0; - _depressed = 0; - _confused = 0; - _paralyzed = 0; - _unconscious = 0; - _dead = 0; - _stoned = 0; - _eradicated = 0; -} - -void Conditions::synchronize(Common::Serializer &s) { - s.syncAsByte(_cursed); - s.syncAsByte(_heartBroken); - s.syncAsByte(_weak); - s.syncAsByte(_poisoned); - s.syncAsByte(_diseased); - s.syncAsByte(_insane); - s.syncAsByte(_inLove); - s.syncAsByte(_drunk); - s.syncAsByte(_asleep); - s.syncAsByte(_depressed); - s.syncAsByte(_confused); - s.syncAsByte(_paralyzed); - s.syncAsByte(_unconscious); - s.syncAsByte(_dead); - s.syncAsByte(_stoned); - s.syncAsByte(_eradicated); -} - -/*------------------------------------------------------------------------*/ - PlayerStruct::PlayerStruct() { _sex = MALE; _race = HUMAN; @@ -96,6 +56,7 @@ PlayerStruct::PlayerStruct() { _currentSpell = 0; _quickOption = 0; _lloydSide = 0; + Common::fill(&_conditions[0], &_conditions[16], 0); _townUnknown = 0; _unknown2 = 0; _currentHp = 0; @@ -161,7 +122,8 @@ void PlayerStruct::synchronize(Common::Serializer &s) { _energyResistence.synchronize(s); _magicResistence.synchronize(s); - _conditions.synchronize(s); + for (int i = 0; i < 16; ++i) + s.syncAsByte(_conditions[i]); s.syncAsUint16LE(_townUnknown); s.syncAsByte(_unknown2); @@ -173,6 +135,26 @@ void PlayerStruct::synchronize(Common::Serializer &s) { s.syncAsByte(_currentCombatSpell); } +Condition PlayerStruct::findCondition() const { + for (int cond = ERADICATED; cond >= CURSED; --cond) { + if (_conditions[cond]) + return (Condition)cond; + } + + return NO_CONDITION; +} + +int PlayerStruct::getYear(int partyYear, bool ignoreTemp) { + int year = MIN(partyYear - _ybDay, 254); + + return ignoreTemp ? year : year + _tempAge; +} + +int PlayerStruct::getMaxHp() { + warning("TODO: getMaxHp"); + return 20; +} + /*------------------------------------------------------------------------*/ void Roster::synchronize(Common::Serializer &s) { @@ -232,6 +214,8 @@ Party::Party() { for (int i = 0; i < TOTAL_CHARACTERS; ++i) Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false); + + _combatPartyCount = 0; } void Party::synchronize(Common::Serializer &s) { @@ -342,4 +326,13 @@ bool Party::checkSkill(Skill skillId) { } } +bool Party::isInParty(int charId) { + for (int i = 0; i < 8; ++i) { + if (_partyMembers[i] == charId) + return true; + } + + return false; +} + } // End of namespace Xeen diff --git a/engines/xeen/party.h b/engines/xeen/party.h index d52153739d..7e5010427f 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -50,9 +50,11 @@ enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3, SPOT_DOORS = 16, DANGER_SENSE = 17 }; -enum ConditionType { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, +enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, - DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11 + DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11, UNCONSCIOUS = 12, + DEAD = 13, STONED = 14, ERADICATED = 15, + NO_CONDITION = 16 }; #define ITEMS_COUNT 36 @@ -71,29 +73,6 @@ public: void synchronize(Common::Serializer &s); }; -class Conditions { - byte _cursed; - byte _heartBroken; - byte _weak; - byte _poisoned; - byte _diseased; - byte _insane; - byte _inLove; - byte _drunk; - byte _asleep; - byte _depressed; - byte _confused; - byte _paralyzed; - byte _unconscious; - byte _dead; - byte _stoned; - byte _eradicated; -public: - Conditions(); - - void synchronize(Common::Serializer &s); -}; - class PlayerStruct { public: Common::String _name; @@ -131,7 +110,7 @@ public: AttributePair _poisonResistence; AttributePair _energyResistence; AttributePair _magicResistence; - Conditions _conditions; + int _conditions[16]; int _townUnknown; int _unknown2; int _currentHp; @@ -143,6 +122,12 @@ public: public: PlayerStruct(); void synchronize(Common::Serializer &s); + + Condition findCondition() const; + + int getYear(int partyYear, bool ignoreTemp); + + int getMaxHp(); }; class Roster: public Common::Array<PlayerStruct> { @@ -154,6 +139,7 @@ public: class Party { public: + // Dynamic data that's saved int _partyCount; int _realPartyCount; int _partyMembers[8]; @@ -208,13 +194,17 @@ public: XeenItem _blacksmithMisc2[ITEMS_COUNT]; bool _characterFlags[30][24]; public: + // Other party related runtime data Common::Array<PlayerStruct *> _activeParty; + int _combatPartyCount; public: Party(); void synchronize(Common::Serializer &s); bool checkSkill(Skill skillId); + + bool isInParty(int charId); }; } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index d7d3fccf98..79e8ba183c 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -232,6 +232,51 @@ const byte TEXT_COLORS[40][4] = { { 0x00, 0xDB, 0xDB, 0xDB }, }; -const char *DIRECTION_TEXT[4] = { "NORTH", "EAST", "SOUTH", "WEST" }; +const char *const DIRECTION_TEXT[4] = { "NORTH", "EAST", "SOUTH", "WEST" }; + +const char *const RACE_NAMES[5] = { "Human", "Elf", "Dwarf", "Gnome", "H-Orc" }; + +const char *const ALIGNMENT_NAMES[3] = { "Good", "Neutral", "Evil" }; + +const char *const SEX_NAMES[2] = { "Male", "Female" }; + +const char *const CLASS_NAMES[11] = { + "Knight", "Paladin", "Archer", "Cleric", "Sorcerer", "Robber", + "Ninja", "Barbarian", "Druid", "Ranger", nullptr +}; + +const char *const CONDITION_NAMES[18] = { + nullptr, "Cursed", "Heart Broken", "Weak", "Poisoned", "Diseased", + "Insane", "In Love", "Drunk", "Asleep", "Depressed", "Confused", + "Paralyzed", "Unconscious", "Dead", "Stone", "Eradicated", "Good" +}; + +const char *const IN_PARTY = "\014""15In Party\014""d"; + +const char *const PARTY_DETAILS = "\015\003l\002\014""00" + "\013""001""\011""035%s" + "\013""009""\011""035%s" + "\013""017""\011""035%s" + "\013""025""\011""035%s" + "\013""001""\011""136%s" + "\013""009""\011""136%s" + "\013""017""\011""136%s" + "\013""025""\011""136%s" + "\013""044""\011""035%s" + "\013""052""\011""035%s" + "\013""060""\011""035%s" + "\013""068""\011""035%s" + "\013""044""\011""136%s" + "\013""052""\011""136%s" + "\013""060""\011""136%s" + "\013""068""\011""136%s"; + +const int FACE_CONDITION_FRAMES[17] = { + 2, 2, 2, 1, 1, 4, 4, 4, 3, 2, 4, 3, 3, 5, 6, 7, 0 +}; + +const int CHAR_FACES_X[6] = { 10, 45, 81, 117, 153, 189 }; + +const int HP_BARS_X[6] = { 13, 50, 86, 122, 158, 194 }; } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index cf4207b814..80febec9b4 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -36,7 +36,27 @@ extern const byte SYMBOLS[20][64]; extern const byte TEXT_COLORS[40][4]; -extern const char *DIRECTION_TEXT[4]; +extern const char *const DIRECTION_TEXT[4]; + +extern const char *const RACE_NAMES[5]; + +extern const char *const CLASS_NAMES[11]; + +extern const char *const ALIGNMENT_NAMES[3]; + +extern const char *const SEX_NAMES[2]; + +extern const char *const CONDITION_NAMES[18]; + +extern const char *const IN_PARTY; + +extern const char *const PARTY_DETAILS; + +extern const int FACE_CONDITION_FRAMES[17]; + +extern const int CHAR_FACES_X[6]; + +extern const int HP_BARS_X[6]; } // End of namespace Xeen diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index f3cbabcfdd..ba2c97b267 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -166,6 +166,22 @@ void Window::writeString(const Common::String &s) { _vm->_screen->writeString(s, _innerBounds); } +void Window::drawList(DrawStruct *items) { + Screen &screen = *_vm->_screen; + + for (; items->_sprites != nullptr; ++items) { + if (items->_frame == -1 || items->_scale == -1) + continue; + + Common::Rect bounds = _innerBounds; + bounds.translate(items->_x, items->_y); + + // TODO: There are two sprite calls in this method. Figure out why + items->_sprites->draw(screen, items->_frame, + Common::Point(items->_x, items->_y)); + } +} + /*------------------------------------------------------------------------*/ /** diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index d62191e501..ae38ec3a03 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -28,6 +28,7 @@ #include "common/array.h" #include "common/rect.h" #include "xeen/font.h" +#include "xeen/sprites.h" #include "xeen/xsurface.h" namespace Xeen { @@ -41,6 +42,19 @@ namespace Xeen { class XeenEngine; class Screen; +struct DrawStruct { + SpriteResource *_sprites; + int _frame; + int _x; + int _y; + int _scale; + int _flags; + + DrawStruct(SpriteResource *sprites, int frame, int x, int y, int scale = 0, int flags = 0) : + _sprites(sprites), _frame(frame), _x(x), _y(y), _scale(scale), _flags(flags) {} + DrawStruct(): _sprites(nullptr), _frame(0), _x(0), _y(0), _scale(0), _flags(0) {} +}; + class Window: public XSurface { private: XeenEngine *_vm; @@ -74,7 +88,10 @@ public: void fill(); - void writeString(const Common::String &s);}; + void writeString(const Common::String &s); + + void drawList(DrawStruct *items); +}; class Screen: public FontSurface { private: diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index a549c15df4..a7210ca871 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -70,6 +70,13 @@ enum XeenDebugChannels { enum Mode { MODE_0 = 0, MODE_1 = 1, + MODE_2 = 2, + MODE_3 = 3, + MODE_4 = 4, + MODE_5 = 5, + MODE_6 = 6, + MODE_7 = 7, + MODE_8 = 8, MODE_9 = 9 }; -- cgit v1.2.3 From ce96094c9bc54266c9742364e656c97446a6ecaf Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 5 Jan 2015 08:11:16 -0500 Subject: XEEN: In progress implementing map loading --- engines/xeen/dialogs.cpp | 25 +- engines/xeen/dialogs.h | 7 +- engines/xeen/dialogs_error.cpp | 77 ++++ engines/xeen/dialogs_error.h | 50 +++ engines/xeen/events.cpp | 16 +- engines/xeen/events.h | 19 +- engines/xeen/files.cpp | 5 +- engines/xeen/files.h | 6 +- engines/xeen/interface.cpp | 221 +++++++++-- engines/xeen/interface.h | 18 +- engines/xeen/map.cpp | 824 +++++++++++++++++++++++++++++++++++++++++ engines/xeen/map.h | 264 +++++++++++++ engines/xeen/module.mk | 2 + engines/xeen/party.cpp | 12 +- engines/xeen/party.h | 11 +- engines/xeen/resources.cpp | 24 ++ engines/xeen/resources.h | 10 + engines/xeen/saves.cpp | 8 + engines/xeen/saves.h | 4 + engines/xeen/screen.cpp | 4 +- engines/xeen/screen.h | 2 +- engines/xeen/sprites.cpp | 8 +- engines/xeen/sprites.h | 2 + engines/xeen/xeen.cpp | 35 +- engines/xeen/xeen.h | 13 +- 25 files changed, 1591 insertions(+), 76 deletions(-) create mode 100644 engines/xeen/dialogs_error.cpp create mode 100644 engines/xeen/dialogs_error.h create mode 100644 engines/xeen/map.cpp create mode 100644 engines/xeen/map.h (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index 70a22d16ee..8e8e7521cb 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -50,19 +50,19 @@ void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResou _buttons.push_back(UIButton(bounds, val, sprites, draw)); } -void ButtonContainer::checkEvents(XeenEngine *vm) { +bool ButtonContainer::checkEvents(XeenEngine *vm) { EventsManager &events = *vm->_events; - events.pollEventsAndWait(); if (events._leftButton) { // Check whether any button is selected - events.debounceMouse(); Common::Point pt = events._mousePos; for (uint i = 0; i < _buttons.size(); ++i) { if (_buttons[i]._bounds.contains(pt)) { + events.debounceMouse(); + _buttonValue = _buttons[i]._value; - return; + return true; } } } else if (events.isKeyPending()) { @@ -70,9 +70,11 @@ void ButtonContainer::checkEvents(XeenEngine *vm) { events.getKey(keyState); if (keyState.ascii >= 32 && keyState.ascii <= 127) { _buttonValue = keyState.ascii; - return; + return true; } } + + return false; } @@ -193,10 +195,10 @@ void ButtonContainer::drawButtons(XSurface *surface) { } } - /*------------------------------------------------------------------------*/ void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) { + _vm->_events->pollEventsAndWait(); checkEvents(_vm); } @@ -231,4 +233,15 @@ void CreditsScreen::execute() { doScroll(_vm, true, false); } +/*------------------------------------------------------------------------*/ + +void PleaseWait::show(XeenEngine *vm) { + if (vm->_mode != MODE_0) { + Window &w = vm->_screen->_windows[9]; + w.open(); + w.writeString(PLEASE_WAIT); + w.update(); + } +} + } // End of namespace Xeen diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h index 61ae73473d..987df6b2f1 100644 --- a/engines/xeen/dialogs.h +++ b/engines/xeen/dialogs.h @@ -54,7 +54,7 @@ protected: void doScroll(XeenEngine *vm, bool drawFlag, bool doFade); - void checkEvents(XeenEngine *vm); + bool checkEvents(XeenEngine *vm); void drawButtons(XSurface *surface); public: @@ -89,6 +89,11 @@ public: static void show(XeenEngine *vm); }; +class PleaseWait { +public: + static void show(XeenEngine *vm); +}; + } // End of namespace Xeen #endif /* XEEN_DIALOGS_H */ diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp new file mode 100644 index 0000000000..c0c072386d --- /dev/null +++ b/engines/xeen/dialogs_error.cpp @@ -0,0 +1,77 @@ +/* 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/scummsys.h" +#include "xeen/dialogs_error.h" +#include "xeen/events.h" +#include "xeen/xeen.h" + +namespace Xeen { + +void ErrorScroll::show(XeenEngine *vm, const Common::String &msg, ErrorWaitType waitType) { + ErrorScroll *dlg = new ErrorScroll(vm); + dlg->execute(msg, waitType); + delete dlg; +} + +void ErrorScroll::execute(const Common::String &msg, ErrorWaitType waitType) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + Window &w = screen._windows[6]; + + Common::String s = Common::String::format("\x03c\v010\t000%s", msg); + w.open(); + w.writeString(s); + w.update(); + + switch (waitType) { + case WT_FREEZE_WAIT: + while (!_vm->shouldQuit() && !events.isKeyPending()) + events.pollEventsAndWait(); + + events.clearEvents(); + break; + case WT_3: + if (w._enabled || _vm->_mode == MODE_17) { + warning("TODO: sub_26D8F"); + break; + } + // Deliberate fall-through + case WT_NONFREEZED_WAIT: + do { + events.updateGameCounter(); + _vm->_interface->draw3d(true); + + events.wait(1, true); + if (checkEvents(_vm)) + break; + } while (!_vm->shouldQuit() && !_buttonValue); + break; + case WT_2: + warning("TODO: sub_26D8F"); + break; + default: + break; + } +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_error.h b/engines/xeen/dialogs_error.h new file mode 100644 index 0000000000..03a6f16cf2 --- /dev/null +++ b/engines/xeen/dialogs_error.h @@ -0,0 +1,50 @@ +/* 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 XEEN_DIALOGS_ERROR_H +#define XEEN_DIALOGS_ERROR_H + +#include "common/array.h" +#include "common/stack.h" +#include "common/rect.h" +#include "xeen/dialogs.h" + +namespace Xeen { + +enum ErrorWaitType { WT_FREEZE_WAIT = 0, WT_NONFREEZED_WAIT = 1, + WT_2 = 2, WT_3 = 3}; + +class ErrorScroll: public ButtonContainer { +private: + XeenEngine *_vm; + + ErrorScroll(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + void execute(const Common::String &msg, ErrorWaitType waitType); +public: + static void show(XeenEngine *vm, const Common::String &msg, + ErrorWaitType waitType = WT_FREEZE_WAIT); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_ERROR_H */ diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp index 285005af98..e0c3b26dc6 100644 --- a/engines/xeen/events.cpp +++ b/engines/xeen/events.cpp @@ -39,6 +39,7 @@ EventsManager::EventsManager(XeenEngine *vm) : _vm(vm), _priorGameCounterTime(0), _keyCode(Common::KEYCODE_INVALID), _leftButton(false), _rightButton(false), _sprites("mouse.icn") { + Common::fill(&_gameCounters[0], &_gameCounters[6], 0); } /** @@ -157,21 +158,6 @@ bool EventsManager::isKeyMousePressed() { return result; } -/** - * Updates the game counter to match the current frame counter - */ -void EventsManager::updateGameCounter() { - _gameCounter = _frameCounter; -} - -/** - * Returns the number of frames elapsed since the last call to - * updateGameCounter() - */ -uint32 EventsManager::timeElapsed() { - return _frameCounter - _gameCounter; -} - bool EventsManager::wait(uint numFrames, bool interruptable) { while (!_vm->shouldQuit() && timeElapsed() < numFrames) { pollEventsAndWait(); diff --git a/engines/xeen/events.h b/engines/xeen/events.h index 7a6a65f4fb..1705bb43d3 100644 --- a/engines/xeen/events.h +++ b/engines/xeen/events.h @@ -39,6 +39,7 @@ private: uint32 _frameCounter; uint32 _priorFrameCounterTime; uint32 _gameCounter; + uint32 _gameCounters[6]; uint32 _priorGameCounterTime; Common::KeyCode _keyCode; SpriteResource _sprites; @@ -52,8 +53,6 @@ public: ~EventsManager(); - uint32 getFrameCounter() { return _frameCounter; } - void setCursor(int cursorId); void showCursor(); @@ -76,9 +75,19 @@ public: bool isKeyMousePressed(); - void updateGameCounter(); - - uint32 timeElapsed(); + void updateGameCounter() { _gameCounter = _frameCounter; } + void timeMark1() { _gameCounters[1] = _frameCounter; } + void timeMark2() { _gameCounters[2] = _frameCounter; } + void timeMark3() { _gameCounters[3] = _frameCounter; } + void timeMark4() { _gameCounters[4] = _frameCounter; } + void timeMark5() { _gameCounters[5] = _frameCounter; } + + uint32 timeElapsed() const { return _frameCounter - _gameCounter; } + uint32 timeElapsed1() const { return _frameCounter - _gameCounters[1]; } + uint32 timeElapsed2() const { return _frameCounter - _gameCounters[2]; } + uint32 timeElapsed3() const { return _frameCounter - _gameCounters[3]; } + uint32 timeElapsed4() const { return _frameCounter - _gameCounters[4]; } + uint32 timeElapsed5() const { return _frameCounter - _gameCounters[5]; } bool wait(uint numFrames, bool interruptable = false); }; diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index 107cde45a1..a0ca2435a1 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -160,10 +160,11 @@ bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEn /** * Instantiates the resource manager */ -void FileManager::init(XeenEngine *vm) { +FileManager::FileManager(XeenEngine *vm) { Common::File f; - if (vm->getGameID() != GType_Clouds) + _isDarkCc = vm->getGameID() != GType_Clouds; + if (_isDarkCc) SearchMan.add("dark", new CCArchive("dark.cc")); SearchMan.add("xeen", new CCArchive("xeen.cc")); SearchMan.add("intro", new CCArchive("intro.cc")); diff --git a/engines/xeen/files.h b/engines/xeen/files.h index 8a028a95c7..3e38ad842c 100644 --- a/engines/xeen/files.h +++ b/engines/xeen/files.h @@ -38,7 +38,11 @@ class XeenEngine; */ class FileManager { public: - static void init(XeenEngine *vm); + bool _isDarkCc; +public: + FileManager(XeenEngine *vm); + + void setGameCc(bool isDarkCc) { _isDarkCc = isDarkCc; } }; /** diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 3a07cecec6..08128e54f0 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -21,6 +21,7 @@ */ #include "xeen/interface.h" +#include "xeen/dialogs_error.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -41,16 +42,18 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { _buttonsLoaded = false; _hiliteChar = -1; Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); + _intrIndex1 = 0; _faceDrawStructs[0] = DrawStruct(nullptr, 0, 0, 0); _faceDrawStructs[1] = DrawStruct(nullptr, 0, 101, 0); _faceDrawStructs[2] = DrawStruct(nullptr, 0, 0, 43); _faceDrawStructs[3] = DrawStruct(nullptr, 0, 101, 43); - - loadSprites(); } -void Interface::loadSprites() { +void Interface::manageCharacters(bool soundPlayed) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + bool flag = false; _globalSprites.load("global.icn"); _borderSprites.load("border.icn"); _spellFxSprites.load("spellfx.icn"); @@ -58,21 +61,21 @@ void Interface::loadSprites() { _blessSprites.load("bless.icn"); _restoreSprites.load("restorex.icn"); _hpSprites.load("hpbars.icn"); -} - -void Interface::setup(bool soundPlayed) { - Screen &screen = *_vm->_screen; - SpriteResource uiSprites("inn.icn"); + _uiSprites.load("inn.icn"); +start: // Get mappings to the active characters in the party _vm->_party._activeParty.resize(_vm->_party._partyCount); for (int i = 0; i < _vm->_party._partyCount; ++i) { - _vm->_party._activeParty[i] = &_vm->_roster[_vm->_party._partyMembers[i]]; + _vm->_party._activeParty[i] = _vm->_roster[_vm->_party._partyMembers[i]]; } _isEarlyGame = _vm->_party._minutes >= 300; - if (_vm->_party._mazeId == 0) { + if (_vm->_party._mazeId != 0) { + _vm->_mode = MODE_0; + _buttonsLoaded = true; + } else { if (!soundPlayed) { warning("TODO: loadSound?"); } @@ -100,25 +103,156 @@ void Interface::setup(bool soundPlayed) { // Add in buttons for the UI _interfaceText = ""; _buttonsLoaded = true; - addButton(Common::Rect(16, 100, 40, 120), 242, &uiSprites, true); - addButton(Common::Rect(52, 100, 76, 120), 243, &uiSprites, true); - addButton(Common::Rect(87, 100, 111, 120), 68, &uiSprites, true); - addButton(Common::Rect(122, 100, 146, 120), 82, &uiSprites, true); - addButton(Common::Rect(157, 100, 181, 120), 67, &uiSprites, true); - addButton(Common::Rect(192, 100, 216, 120), 88, &uiSprites, true); - addButton(Common::Rect(), 27, &uiSprites, false); - addButton(Common::Rect(16, 16, 48, 48), 49, &uiSprites, false); - addButton(Common::Rect(117, 16, 139, 48), 50, &uiSprites, false); - addButton(Common::Rect(16, 59, 48, 81), 51, &uiSprites, false); - addButton(Common::Rect(117, 59, 149, 81), 52, &uiSprites, false); + addButton(Common::Rect(16, 100, 40, 120), 242, &_uiSprites, true); + addButton(Common::Rect(52, 100, 76, 120), 243, &_uiSprites, true); + addButton(Common::Rect(87, 100, 111, 120), 68, &_uiSprites, true); + addButton(Common::Rect(122, 100, 146, 120), 82, &_uiSprites, true); + addButton(Common::Rect(157, 100, 181, 120), 67, &_uiSprites, true); + addButton(Common::Rect(192, 100, 216, 120), 88, &_uiSprites, true); + addButton(Common::Rect(), 27, &_uiSprites, false); + addButton(Common::Rect(16, 16, 48, 48), 49, &_uiSprites, false); + addButton(Common::Rect(117, 16, 139, 48), 50, &_uiSprites, false); + addButton(Common::Rect(16, 59, 48, 81), 51, &_uiSprites, false); + addButton(Common::Rect(117, 59, 149, 81), 52, &_uiSprites, false); setupBackground(); - screen._windows[11].open(); - setupFaces(0, xeenSideChars, 0); - screen._windows[11].writeString(_interfaceText); + Window &w = screen._windows[11]; + w.open(); + setupFaces(0, xeenSideChars, false); + w.writeString(_interfaceText); + w.drawList(&_faceDrawStructs[0], 4); + + _uiSprites.draw(w, 0, Common::Point(16, 100)); + _uiSprites.draw(w, 2, Common::Point(52, 100)); + _uiSprites.draw(w, 4, Common::Point(87, 100)); + _uiSprites.draw(w, 6, Common::Point(122, 100)); + _uiSprites.draw(w, 8, Common::Point(157, 100)); + _uiSprites.draw(w, 10, Common::Point(192, 100)); + + screen.loadPalette("mm4.pal"); + + if (flag) { + screen._windows[0].update(); + events.setCursor(0); + screen.fadeIn(4); + } else { + if (_vm->getGameID() == GType_DarkSide) { + screen.fadeOut(4); + screen._windows[0].update(); + } + + doScroll(_vm, false, false); + events.setCursor(0); + + if (_vm->getGameID() == GType_DarkSide) { + screen.fadeIn(4); + } + } // TODO + bool breakFlag = false; + while (!_vm->shouldQuit() && !breakFlag) { + events.pollEventsAndWait(); + checkEvents(_vm); + + switch (_buttonValue) { + case Common::KEYCODE_ESCAPE: + case Common::KEYCODE_SPACE: + case Common::KEYCODE_e: + case Common::KEYCODE_x: + if (_vm->_party._partyCount == 0) { + ErrorScroll::show(_vm, NO_ONE_TO_ADVENTURE_WITH); + } else { + if (_vm->_mode != MODE_0) { + for (_intrIndex1 = 4; _intrIndex1 >= 0; --_intrIndex1) { + events.updateGameCounter(); + drawViewBackground(_intrIndex1); + w.update(); + + while (events.timeElapsed() < 1) + events.pollEventsAndWait(); + } + } + + w.close(); + _vm->_party._realPartyCount = _vm->_party._partyCount; + _vm->_party._mazeId = _vm->_party._priorMazeId; + + _vm->_party.copyPartyToRoster(_vm->_roster); + _vm->_saves->writeCharFile(); + breakFlag = true; + break; + } + break; + case Common::KEYCODE_1: + break; + case Common::KEYCODE_2: + break; + case Common::KEYCODE_3: + break; + case Common::KEYCODE_4: + break; + case Common::KEYCODE_c: + if (xeenSideChars.size() == 24) { + ErrorScroll::show(_vm, YOUR_ROSTER_IS_FULL); + } else { + screen.fadeOut(4); + w.close(); + addCharacterToRoster(); + _vm->_saves->writeCharFile(); + screen.fadeOut(4); + flag = true; + _buttonsLoaded = true; + goto start; + } + break; + case Common::KEYCODE_d: + break; + case Common::KEYCODE_r: + if (_vm->_party._partyCount > 0) { + // TODO + } + break; + case 201: + // TODO + break; + case 202: + // TODO + break; + case 203: + // TODO + break; + case 204: + // TODO + break; + case 205: + // TODO + break; + case 206: + // TODO + break; + case 242: + // TODO + break; + case 243: + // TODO + break; + default: + break; + } + } } + + for (int i = 0; i < TOTAL_CHARACTERS; ++i) + _charFaces[i].clear(); + _globalSprites.clear(); + _borderSprites.clear(); + _spellFxSprites.clear(); + _fecpSprites.clear(); + _blessSprites.clear(); + _restoreSprites.clear(); + _hpSprites.clear(); + _uiSprites.clear(); } void Interface::loadCharIcons(int numChars) { @@ -244,7 +378,7 @@ void Interface::assembleBorder() { screen._windows[12].frame(); } -void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, int v3) { +void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag) { Common::String playerNames[4]; Common::String playerRaces[4]; Common::String playerSex[4]; @@ -271,7 +405,7 @@ void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, int playerClass[posIndex] = CLASS_NAMES[ps._class]; } - charIconsPrint(v3); + charIconsPrint(updateFlag); // Set up the sprite set to use for each face charId = xeenSideChars[charIndex]; @@ -300,7 +434,7 @@ void Interface::charIconsPrint(bool updateFlag) { for (int idx = 0; idx < (stateFlag ? _vm->_party._combatPartyCount : _vm->_party._partyCount); ++idx) { int charIndex = stateFlag ? _combatCharIds[idx] : idx; - PlayerStruct &ps = *_vm->_party._activeParty[charIndex]; + PlayerStruct &ps = _vm->_party._activeParty[charIndex]; Condition charCondition = ps.findCondition(); int charFrame = FACE_CONDITION_FRAMES[charCondition]; @@ -316,7 +450,7 @@ void Interface::charIconsPrint(bool updateFlag) { for (int idx = 0; idx < (stateFlag ? _vm->_party._combatPartyCount : _vm->_party._partyCount); ++idx) { int charIndex = stateFlag ? _combatCharIds[idx] : idx; - PlayerStruct &ps = *_vm->_party._activeParty[charIndex]; + PlayerStruct &ps = _vm->_party._activeParty[charIndex]; // Draw the Hp bar int maxHp = ps.getMaxHp(); @@ -343,4 +477,35 @@ void Interface::charIconsPrint(bool updateFlag) { screen._windows[33].update(); } +void Interface::drawViewBackground(int bgType) { + if (bgType >= 4) + return; + + if (bgType == 0) { + // Totally black background + _vm->_screen->fillRect(Common::Rect(8, 8, 224, 140), 0); + } else { + const byte *lookup = BACKGROUND_XLAT + bgType; + for (int yp = 8; yp < 140; ++yp) { + byte *destP = (byte *)_vm->_screen->getBasePtr(8, yp); + for (int xp = 8; xp < 224; ++xp, ++destP) + *destP = lookup[*destP]; + } + } +} + +void Interface::addCharacterToRoster() { + error("TODO"); +} + +void Interface::draw3d(bool flag) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + + if (!screen._windows[11]._enabled) + return; + + warning("TODO"); +} + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 3ceb08239e..1ed7afe628 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -43,6 +43,7 @@ private: SpriteResource _blessSprites; SpriteResource _restoreSprites; SpriteResource _hpSprites; + SpriteResource _uiSprites; SpriteResource _charFaces[TOTAL_CHARACTERS]; SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; DrawStruct _faceDrawStructs[4]; @@ -61,22 +62,27 @@ private: bool _buttonsLoaded; Common::String _interfaceText; int _hiliteChar; - - void loadSprites(); - - void loadCharIcons(int numChars); + int _intrIndex1; void assembleBorder(); void setupBackground(); - void setupFaces(int charIndex, Common::Array<int> xeenSideChars, int v3); + void setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag); void charIconsPrint(bool updateFlag); + + void drawViewBackground(int bgType); + + void addCharacterToRoster(); public: Interface(XeenEngine *vm); - void setup(bool soundPlayed); + void manageCharacters(bool soundPlayed); + + void loadCharIcons(int numChars); + + void draw3d(bool flag); }; } // End of namespace Xeen diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp new file mode 100644 index 0000000000..d797179e15 --- /dev/null +++ b/engines/xeen/map.cpp @@ -0,0 +1,824 @@ +/* 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/serializer.h" +#include "xeen/map.h" +#include "xeen/resources.h" +#include "xeen/saves.h" +#include "xeen/screen.h" +#include "xeen/xeen.h" + +namespace Xeen { + +MonsterStruct::MonsterStruct() { + _experience = 0; + _hp = 0; + _accuracy = 0; + _speed = 0; + _numberOfAttacks = 0; + _hatesClass = CLASS_KNIGHT; + _strikes = 0; + _dmgPerStrike = 0; + _attackType = DT_PHYSICAL; + _specialAttack = SA_NONE; + _hitChance = 0; + _rangeAttack = 0; + _monsterType = MONSTER_0; + _fireResistence = 0; + _electricityResistence = 0; + _coldResistence = 0; + _poisonResistence = 0; + _energyResistence = 0; + _magicResistence = 0; + _phsyicalResistence = 0; + _field29 = 0; + _gold = 0; + _gems = 0; + _itemDrop = 0; + _flying = 0; + _imageNumber = 0; + _loopAnimation = 0; + _animationEffect = 0; + _field32 = 0; +} + +MonsterStruct::MonsterStruct(Common::String name, int experience, int hp, int accuracy, + int speed, int numberOfAttacks, CharacterClass hatesClass, int strikes, + int dmgPerStrike, DamageType attackType, SpecialAttack specialAttack, + int hitChance, int rangeAttack, MonsterType monsterType, + int fireResistence, int electricityResistence, int coldResistence, + int poisonResistence, int energyResistence, int magicResistence, + int phsyicalResistence, int field29, int gold, int gems, int itemDrop, + int flying, int imageNumber, int loopAnimation, int animationEffect, + int field32, Common::String attackVoc): + _name(name), _experience(experience), _hp(hp), _accuracy(accuracy), + _speed(speed), _numberOfAttacks(numberOfAttacks), _hatesClass(hatesClass), + _strikes(strikes), _dmgPerStrike(dmgPerStrike), _attackType(attackType), + _specialAttack(specialAttack), _hitChance(hitChance), _rangeAttack(rangeAttack), + _monsterType(monsterType), _fireResistence(fireResistence), + _electricityResistence(electricityResistence), _coldResistence(coldResistence), + _poisonResistence(poisonResistence), _energyResistence(energyResistence), + _magicResistence(magicResistence), _phsyicalResistence(phsyicalResistence), + _field29(field29), _gold(gold), _gems(gems), _itemDrop(itemDrop), + _flying(flying), _imageNumber(imageNumber), _loopAnimation(loopAnimation), + _animationEffect(animationEffect), _field32(field32), _attackVoc(attackVoc) { +} + + +void MonsterStruct::synchronize(Common::SeekableReadStream &s) { + _experience = s.readByte(); + _hp = s.readByte(); + _accuracy = s.readByte(); + _speed = s.readByte(); + _numberOfAttacks = s.readByte(); + _hatesClass = CLASS_KNIGHT; + _strikes = s.readByte(); + _dmgPerStrike = s.readByte(); + _attackType = (DamageType)s.readByte(); + _specialAttack = (SpecialAttack)s.readByte(); + _hitChance = s.readByte(); + _rangeAttack = s.readByte(); + _monsterType = (MonsterType)s.readByte(); + _fireResistence = s.readByte(); + _electricityResistence = s.readByte(); + _coldResistence = s.readByte(); + _poisonResistence = s.readByte(); + _energyResistence = s.readByte(); + _magicResistence = s.readByte(); + _phsyicalResistence = s.readByte(); + _field29 = s.readByte(); + _gold = s.readByte(); + _gems = s.readByte(); + _itemDrop = s.readByte(); + _flying = s.readByte(); + _imageNumber = s.readByte(); + _loopAnimation = s.readByte(); + _animationEffect = s.readByte(); + _field32 = s.readByte(); + + char attackVoc[9]; + s.read(attackVoc, 9); + attackVoc[8] = '\0'; + _attackVoc = Common::String(attackVoc); +} + +MonsterData::MonsterData() { + push_back(MonsterStruct("", 0, 0, 0, 0, 0, CLASS_KNIGHT, 1, 1, DT_PHYSICAL, + SA_NONE, 1, 0, MONSTER_0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 100, "Slime")); + push_back(MonsterStruct("Whirlwind", 250000, 1000, 10, 250, 1, CLASS_15, 5, + 100, DT_PHYSICAL, SA_CONFUSE, 250, 0, MONSTER_0, 100, + 100, 100, 100, 0, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 176, + "airmon")); + push_back(MonsterStruct("Annihilator", 1000000, 1500, 40, 200, 12, CLASS_16, 5, + 50, DT_ENERGY, SA_NONE, 1, 1, MONSTER_0, 80, 80, 100, + 100, 0, 0, 80, 0, 0, 0, 0, 0, 2, 0, 0, 102, "alien1")); + push_back(MonsterStruct("Autobot", 1000000, 2500, 100, 200, 2, CLASS_16, 5, + 100, DT_ENERGY, SA_NONE, 1, 0, MONSTER_0, 50, 50, 100, + 100, 0, 0, 50, 0, 0, 0, 0, 1, 3, 0, 0, 101, "alien2")); + push_back(MonsterStruct("Sewer Stalker", 50000, 250, 30, 25, 1, CLASS_16, 3, + 100, DT_PHYSICAL, SA_NONE, 50, 0, MONSTER_ANIMAL, 0, + 0, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 113, + "iguana")); + push_back(MonsterStruct("Armadillo", 60000, 800, 50, 15, 1, CLASS_16, 100, 6, + DT_PHYSICAL, SA_BREAKWEAPON, 60, 0, MONSTER_ANIMAL, + 50, 0, 80, 80, 50, 0, 50, 0, 0, 0, 0, 0, 5, 1, 0, 113, + "unnh")); + push_back(MonsterStruct("Barbarian", 5000, 50, 5, 40, 3, CLASS_SORCERER, 1, 20, + DT_PHYSICAL, SA_NONE, 20, 1, MONSTER_HUMANOID, 0, 0, + 0, 0, 0, 0, 0, 0, 100, 0, 3, 0, 6, 0, 0, 100, + "barbarch")); + push_back(MonsterStruct("Electrapede", 10000, 200, 10, 50, 1, CLASS_PALADIN, + 50, 1, DT_ELECTRICAL, SA_PARALYZE, 1, 0, + MONSTER_INSECT, 50, 100, 50, 50, 50, 0, 0, 0, 0, 0, 0, + 0, 7, 1, 0, 107, "centi")); + push_back(MonsterStruct("Cleric of Mok", 30000, 125, 10, 40, 1, CLASS_CLERIC, + 250, 1, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, + 10, 100, 10, 10, 10, 10, 0, 0, 0, 10, 0, 0, 8, 0, 0, + 117, "cleric")); + push_back(MonsterStruct("Mok Heretic", 50000, 150, 12, 50, 1, CLASS_CLERIC, + 500, 1, DT_1, SA_NONE, 1, 1, MONSTER_HUMANOID, 20, 50, + 20, 20, 20, 30, 0, 0, 0, 25, 4, 0, 8, 0, 0, 117, + "cleric")); + push_back(MonsterStruct("Mantis Ant", 40000, 300, 30, 40, 2, CLASS_16, 2, 100, + DT_PHYSICAL, SA_POISON, 30, 0, MONSTER_INSECT, 0, 0, + 0, 100, 0, 0, 30, 0, 0, 0, 0, 0, 10, 0, 0, 104, + "spell001")); + push_back(MonsterStruct("Cloud Dragon", 500000, 2000, 40, 150, 1, CLASS_15, + 600, 1, DT_COLD, SA_NONE, 1, 1, MONSTER_DRAGON, 0, 50, + 100, 100, 50, 25, 50, 0, 0, 10, 0, 0, 11, 0, 0, 140, + "tiger1")); + push_back(MonsterStruct("Phase Dragon", 2000000, 4000, 80, 200, 1, CLASS_15, + 750, 1, DT_COLD, SA_NONE, 1, 1, MONSTER_DRAGON, 0, 50, + 100, 100, 80, 50, 50, 0, 0, 20, 0, 0, 11, 0, 10, 140, + "Begger")); + push_back(MonsterStruct("Green Dragon", 500000, 2500, 50, 150, 1, CLASS_15, + 500, 1, DT_FIRE, SA_NONE, 1, 1, MONSTER_DRAGON, 100, + 50, 0, 100, 50, 25, 50, 0, 0, 10, 0, 0, 13, 0, 0, 140, + "tiger1")); + push_back(MonsterStruct("Energy Dragon", 2000000, 5000, 100, 250, 1, CLASS_15, + 1000, 1, DT_ENERGY, SA_NONE, 1, 1, MONSTER_DRAGON, 80, + 80, 60, 100, 100, 30, 50, 0, 0, 20, 0, 0, 13, 0, 7, + 140, "begger")); + push_back(MonsterStruct("Dragon Mummy", 2000000, 3000, 30, 100, 1, + CLASS_CLERIC, 2000, 2, DT_PHYSICAL, SA_DISEASE, 200, + 0, MONSTER_DRAGON, 0, 80, 100, 100, 0, 10, 90, 0, 0, 0, + 0, 0, 15, 0, 0, 140, "dragmum")); + push_back(MonsterStruct("Scraps", 2000000, 3000, 30, 100, 1, CLASS_16, 2000, 2, + DT_PHYSICAL, SA_NONE, 200, 0, MONSTER_DRAGON, 0, 80, + 100, 100, 0, 10, 90, 0, 0, 0, 0, 0, 15, 0, 0, 140, + "dragmum")); + push_back(MonsterStruct("Earth Blaster", 250000, 1000, 10, 100, 1, CLASS_15, 5, + 100, DT_PHYSICAL, SA_NONE, 200, 0, MONSTER_0, 100, 90, + 90, 100, 0, 0, 90, 0, 0, 0, 0, 0, 17, 0, 0, 100, + "earthmon")); + push_back(MonsterStruct("Beholder Bat", 10000, 75, 15, 80, 1, CLASS_15, 5, 5, + DT_FIRE, SA_NONE, 1, 0, MONSTER_0, 100, 50, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 18, 0, 0, 120, "eyeball")); + push_back(MonsterStruct("Fire Blower", 250000, 1000, 20, 60, 1, CLASS_15, 5, + 100, DT_FIRE, SA_NONE, 1, 0, MONSTER_0, 100, 50, 0, + 100, 50, 0, 50, 0, 0, 0, 0, 0, 19, 0, 0, 110, "fire")); + push_back(MonsterStruct("Hell Hornet", 50000, 250, 30, 50, 2, CLASS_DRUID, 2, + 250, DT_POISON, SA_WEAKEN, 1, 0, MONSTER_INSECT, 50, + 50, 50, 100, 50, 0, 50, 0, 0, 0, 0, 1, 20, 0, 0, 123, + "insect")); + push_back(MonsterStruct("Gargoyle", 30000, 150, 35, 30, 2, CLASS_16, 5, 50, + DT_PHYSICAL, SA_NONE, 60, 0, MONSTER_0, 0, 0, 0, 0, 0, + 20, 0, 0, 0, 0, 0, 0, 21, 0, 10, 100, "gargrwl")); + push_back(MonsterStruct("Giant", 100000, 500, 25, 45, 2, CLASS_16, 100, 5, + DT_PHYSICAL, SA_UNCONSCIOUS, 100, 0, MONSTER_0, 0, 0, + 0, 0, 0, 0, 0, 0, 1000, 0, 5, 0, 22, 0, 0, 100, + "giant")); + push_back(MonsterStruct("Goblin", 1000, 10, 5, 30, 2, CLASS_16, 2, 6, + DT_PHYSICAL, SA_NONE, 1, 0, MONSTER_0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 131, "gremlin")); + push_back(MonsterStruct("Onyx Golem", 1000000, 10000, 50, 100, 1, CLASS_15, 2, + 250, DT_1, SA_DRAINSP, 1, 0, MONSTER_GOLEM, 100, 100, + 100, 100, 100, 100, 50, 0, 0, 100, 0, 1, 24, 0, 10, + 100, "golem")); + push_back(MonsterStruct("Gremlin", 2000, 20, 7, 35, 2, CLASS_16, 2, 10, + DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 101, "gremlink")); + push_back(MonsterStruct("Gremlin Guard", 3000, 50, 10, 35, 2, CLASS_16, 6, 5, + DT_PHYSICAL, SA_NONE, 20, 0, MONSTER_0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 101, "gremlink")); + push_back(MonsterStruct("Griffin", 60000, 800, 35, 150, 2, CLASS_KNIGHT, 50, 6, + DT_PHYSICAL, SA_NONE, 150, 0, MONSTER_ANIMAL, 0, 0, 0, + 0, 0, 80, 0, 0, 0, 0, 0, 0, 27, 0, 0, 120, "screech")); + push_back(MonsterStruct("Gamma Gazer", 1000000, 5000, 60, 200, 7, CLASS_16, 10, + 20, DT_ENERGY, SA_NONE, 1, 0, MONSTER_0, 100, 100, 0, + 100, 100, 0, 60, 0, 0, 0, 0, 0, 28, 0, 0, 140, "hydra")); + push_back(MonsterStruct("Iguanasaurus", 100000, 2500, 20, 30, 1, CLASS_16, 10, + 50, DT_PHYSICAL, SA_INSANE, 150, 0, MONSTER_ANIMAL, 50, + 50, 50, 50, 50, 0, 20, 0, 0, 0, 0, 0, 29, 0, 0, 113, + "iguana")); + push_back(MonsterStruct("Slayer Knight", 50000, 500, 30, 50, 1, CLASS_PALADIN, + 2, 250, DT_PHYSICAL, SA_NONE, 100, 0, MONSTER_HUMANOID, + 50, 50, 50, 50, 50, 0, 0, 0, 50, 0, 5, 0, 30, 0, 0, + 141, "knight")); + push_back(MonsterStruct("Death Knight", 100000, 750, 50, 80, 2, CLASS_PALADIN, + 2, 250, DT_PHYSICAL, SA_NONE, 150, 0, MONSTER_HUMANOID, + 50, 50, 50, 50, 50, 10, 0, 0, 100, 0, 6, 0, 30, 0, 0, + 141, "knight")); + push_back(MonsterStruct("Lava Dweller", 500000, 1500, 30, 40, 1, CLASS_15, 5, + 100, DT_FIRE, SA_NONE, 1, 0, MONSTER_0, 100, 100, 0, + 100, 50, 0, 50, 0, 0, 0, 0, 0, 19, 0, 0, 110, "fire")); + push_back(MonsterStruct("Lava Roach", 50000, 500, 20, 70, 1, CLASS_16, 5, 50, + DT_FIRE, SA_NONE, 1, 0, MONSTER_INSECT, 100, 100, 0, + 100, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 131, "Phantom")); + push_back(MonsterStruct("Power Lich", 200000, 500, 20, 60, 1, CLASS_15, 10, 10, + DT_1, SA_UNCONSCIOUS, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0, + 0, 80, 70, 0, 0, 0, 0, 1, 34, 0, 0, 141, "lich")); + push_back(MonsterStruct("Mystic Mage", 100000, 200, 20, 70, 1, CLASS_15, 10, + 20, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_0, 50, 100, + 50, 50, 50, 30, 0, 0, 0, 50, 0, 1, 35, 0, 0, 163, + "monsterb")); + push_back(MonsterStruct("Magic Mage", 200000, 300, 25, 80, 1, CLASS_15, 10, 30, + DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_0, 50, 100, 50, + 50, 50, 50, 0, 0, 0, 75, 0, 1, 35, 0, 0, 163, + "monsterb")); + push_back(MonsterStruct("Minotaur", 250000, 3000, 80, 120, 1, CLASS_16, 100, 4, + DT_PHYSICAL, SA_AGING, 150, 0, MONSTER_0, 0, 0, 10, 0, + 0, 50, 60, 0, 0, 0, 0, 0, 37, 0, 0, 141, "stonegol")); + push_back(MonsterStruct("Gorgon", 250000, 4000, 90, 100, 1, CLASS_16, 100, 3, + DT_PHYSICAL, SA_STONE, 100, 0, MONSTER_0, 0, 0, 0, 0, + 0, 60, 70, 0, 0, 0, 0, 0, 37, 0, 0, 141, "stonegol")); + push_back(MonsterStruct("Higher Mummy", 100000, 400, 20, 60, 1, CLASS_CLERIC, + 10, 40, DT_PHYSICAL, SA_CURSEITEM, 100, 0, + MONSTER_UNDEAD, 0, 50, 50, 100, 50, 20, 75, 0, 0, 0, 0, + 0, 39, 0, 0, 141, "mummy")); + push_back(MonsterStruct("Orc Guard", 5000, 60, 10, 20, 1, CLASS_12, 3, 10, + DT_PHYSICAL, SA_NONE, 20, 0, MONSTER_HUMANOID, 0, 0, + 0, 0, 0, 0, 0, 0, 50, 0, 2, 0, 40, 0, 0, 125, "orc")); + push_back(MonsterStruct("Octopod", 250000, 2500, 40, 80, 1, CLASS_15, 2, 100, + DT_POISON, SA_POISON, 1, 0, MONSTER_ANIMAL, 0, 0, 50, + 100, 0, 0, 0, 0, 0, 0, 0, 1, 41, 0, 0, 101, "photon")); + push_back(MonsterStruct("Ogre", 10000, 100, 15, 30, 1, CLASS_16, 4, 10, + DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 0, 0, 0, 0, 0, + 0, 0, 0, 100, 0, 0, 0, 42, 0, 0, 136, "ogre")); + push_back(MonsterStruct("Orc Shaman", 10000, 50, 15, 30, 1, CLASS_15, 5, 5, + DT_COLD, SA_SLEEP, 1, 1, MONSTER_HUMANOID, 0, 0, 0, 0, + 0, 10, 0, 0, 75, 10, 2, 0, 43, 0, 0, 125, "fx7")); + push_back(MonsterStruct("Sabertooth", 10000, 100, 20, 60, 3, CLASS_16, 5, 10, + DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_ANIMAL, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 1, 0, 101, "saber")); + push_back(MonsterStruct("Sand Flower", 10000, 100, 10, 50, 5, CLASS_16, 5, 5, + DT_PHYSICAL, SA_INLOVE, 50, 0, MONSTER_0, 0, 0, 0, 0, + 0, 50, 50, 0, 0, 0, 0, 0, 45, 0, 0, 106, "sand")); + push_back(MonsterStruct("Killer Cobra", 25000, 1000, 25, 100, 1, CLASS_16, 2, + 100, DT_PHYSICAL, SA_AGING, 30, 0, MONSTER_ANIMAL, 0, + 0, 0, 100, 0, 50, 0, 0, 0, 0, 0, 0, 46, 0, 0, 100, + "hiss")); + push_back(MonsterStruct("Sewer Rat", 2000, 40, 5, 35, 1, CLASS_16, 3, 10, + DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_ANIMAL, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 136, "rat")); + push_back(MonsterStruct("Sewer Slug", 1000, 25, 2, 25, 1, CLASS_16, 2, 10, + DT_PHYSICAL, SA_NONE, 5, 0, MONSTER_INSECT, 0, 0, 0, + 100, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 111, "zombie")); + push_back(MonsterStruct("Skeletal Lich", 500000, 2000, 30, 200, 1, + CLASS_SORCERER, 1000, 1, DT_ENERGY, SA_ERADICATE, 1, 1, + MONSTER_UNDEAD, 80, 70, 80, 100, 100, 50, 50, 0, 0, 0, + 0, 0, 49, 0, 0, 140, "elecbolt")); + push_back(MonsterStruct("Enchantress", 40000, 100, 25, 60, 1, CLASS_CLERIC, 3, + 150, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, + 10, 100, 10, 10, 10, 20, 0, 0, 0, 20, 0, 0, 50, 0, 0, + 163, "disint")); + push_back(MonsterStruct("Sorceress", 80000, 200, 30, 80, 1, CLASS_15, 2, 50, + DT_1, SA_NONE, 1, 1, MONSTER_HUMANOID, 10, 20, 10, 10, + 10, 80, 0, 0, 0, 50, 5, 0, 50, 0, 0, 163, "disint")); + push_back(MonsterStruct("Arachnoid", 4000, 50, 10, 40, 1, CLASS_16, 3, 5, + DT_POISON, SA_POISON, 1, 0, MONSTER_INSECT, 0, 0, 0, + 100, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 104, "web")); + push_back(MonsterStruct("Medusa Sprite", 5000, 30, 5, 30, 1, CLASS_RANGER, 3, + 3, DT_PHYSICAL, SA_STONE, 10, 0, MONSTER_0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 53, 0, 0, 42, "hiss")); + push_back(MonsterStruct("Rogue", 5000, 50, 10, 30, 1, CLASS_ROBBER, 1, 60, + DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_HUMANOID, 0, 0, + 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 54, 0, 0, 100, "thief")); + push_back(MonsterStruct("Thief", 10000, 100, 15, 40, 1, CLASS_ROBBER, 1, 100, + DT_PHYSICAL, SA_NONE, 20, 0, MONSTER_HUMANOID, 0, 0, + 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 54, 0, 0, 100, + "thief")); + push_back(MonsterStruct("Troll Grunt", 10000, 100, 5, 50, 1, CLASS_16, 2, 25, + DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 50, 50, 50, + 50, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 136, "troll")); + push_back(MonsterStruct("Vampire", 200000, 400, 30, 80, 1, CLASS_CLERIC, 10, + 10, DT_PHYSICAL, SA_WEAKEN, 100, 0, MONSTER_UNDEAD, 50, + 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 57, 0, 0, 42, + "vamp")); + push_back(MonsterStruct("Vampire Lord", 300000, 500, 35, 100, 1, CLASS_CLERIC, + 10, 30, DT_PHYSICAL, SA_SLEEP, 120, 0, MONSTER_UNDEAD, + 50, 50, 50, 50, 50, 50, 70, 0, 0, 0, 0, 0, 58, 0, 0, + 42, "vamp")); + push_back(MonsterStruct("Vulture Roc", 200000, 2500, 50, 150, 1, CLASS_16, 5, + 60, DT_PHYSICAL, SA_NONE, 100, 0, MONSTER_ANIMAL, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 59, 0, 0, 120, "vulture")); + push_back(MonsterStruct("Sewer Hag", 50000, 75, 10, 40, 1, CLASS_PALADIN, 10, + 25, DT_ELECTRICAL, SA_INSANE, 1, 1, MONSTER_HUMANOID, + 0, 100, 0, 100, 0, 20, 0, 0, 0, 10, 0, 0, 62, 0, 0, + 108, "elecspel")); + push_back(MonsterStruct("Tidal Terror", 500000, 1000, 10, 200, 1, CLASS_15, 5, + 100, DT_COLD, SA_NONE, 1, 0, MONSTER_0, 100, 50, 50, + 100, 50, 0, 100, 0, 0, 0, 0, 1, 61, 0, 0, 101, + "splash3")); + push_back(MonsterStruct("Witch", 80000, 150, 15, 70, 1, CLASS_15, 10, 10, + DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, 0, 100, + 0, 20, 0, 20, 0, 0, 0, 10, 0, 0, 63, 0, 0, 114, + "elecspel")); + push_back(MonsterStruct("Coven Leader", 120000, 250, 20, 100, 1, CLASS_15, 10, + 15, DT_ENERGY, SA_DRAINSP, 1, 1, MONSTER_HUMANOID, 10, + 100, 0, 50, 100, 50, 0, 0, 0, 20, 6, 0, 63, 0, 10, 114, + "elecspel")); + push_back(MonsterStruct("Master Wizard", 120000, 500, 25, 150, 2, CLASS_KNIGHT, + 10, 40, DT_FIRE, SA_NONE, 1, 1, MONSTER_HUMANOID, 100, + 50, 50, 50, 50, 50, 0, 0, 0, 50, 0, 0, 64, 0, 0, 163, + "boltelec")); + push_back(MonsterStruct("Wizard", 60000, 250, 20, 125, 1, CLASS_PALADIN, 10, + 25, DT_1, SA_NONE, 1, 1, MONSTER_HUMANOID, 50, 30, 30, + 30, 30, 30, 0, 0, 0, 20, 0, 0, 65, 0, 0, 163, "wizard")); + push_back(MonsterStruct("Dark Wolf", 10000, 70, 10, 70, 3, CLASS_16, 3, 8, + DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_ANIMAL, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 1, 0, 100, "wolf")); + push_back(MonsterStruct("Screamer", 500000, 3000, 50, 200, 1, CLASS_15, 10, 20, + DT_POISON, SA_POISON, 1, 0, MONSTER_0, 0, 0, 0, 100, 0, + 0, 60, 0, 0, 0, 0, 0, 67, 0, 0, 110, "dragon")); + push_back(MonsterStruct("Cult Leader", 100000, 100, 20, 60, 1, CLASS_15, 10, + 10, DT_ENERGY, SA_NONE, 1, 1, MONSTER_HUMANOID, 50, 50, + 50, 50, 100, 50, 0, 0, 0, 100, 6, 0, 8, 0, 0, 100, + "cleric")); + push_back(MonsterStruct("Mega Dragon", 100000000, 64000, 100, 200, 1, CLASS_15, + 10, 200, DT_ENERGY, SA_ERADICATE, 1, 1, MONSTER_DRAGON, + 100, 100, 100, 100, 100, 100, 90, 0, 0, 232, 0, 0, 11, + 0, 7, 100, "tiger1")); + push_back(MonsterStruct("Gettlewaithe", 5000, 100, 15, 35, 2, CLASS_16, 5, 5, + DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_0, 0, 0, 0, 0, 0, + 0, 0, 0, 2000, 0, 5, 0, 25, 0, 0, 100, "gremlin")); + push_back(MonsterStruct("Doom Knight", 500000, 1000, 50, 100, 4, CLASS_PALADIN, + 2, 250, DT_PHYSICAL, SA_DEATH, 150, 0, + MONSTER_HUMANOID, 80, 80, 80, 80, 80, 20, 0, 0, 200, + 0, 7, 0, 30, 0, 10, 100, "knight")); + push_back(MonsterStruct("Sandro", 200000, 1000, 20, 75, 1, CLASS_15, 10, 10, + DT_1, SA_DEATH, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0, 0, + 90, 80, 0, 0, 100, 7, 1, 34, 0, 10, 100, "lich")); + push_back(MonsterStruct("Mega Mage", 500000, 500, 35, 100, 1, CLASS_15, 10, 40, + DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_0, 80, 100, 80, + 80, 80, 80, 0, 0, 0, 100, 6, 1, 35, 0, 11, 100, + "monsterb")); + push_back(MonsterStruct("Orc Elite", 15000, 200, 15, 40, 2, CLASS_12, 5, 10, + DT_PHYSICAL, SA_NONE, 20, 0, MONSTER_HUMANOID, 0, 0, + 0, 0, 0, 0, 0, 0, 100, 0, 3, 0, 40, 0, 0, 100, "orc")); + push_back(MonsterStruct("Shaalth", 20000, 300, 15, 50, 1, CLASS_15, 5, 10, + DT_COLD, SA_SLEEP, 1, 0, MONSTER_HUMANOID, 0, 0, 0, 0, + 0, 20, 0, 0, 1000, 50, 5, 0, 43, 0, 10, 100, "fx7")); + push_back(MonsterStruct("Rooka", 5000, 60, 5, 40, 1, CLASS_16, 3, 10, + DT_PHYSICAL, SA_DISEASE, 15, 0, MONSTER_ANIMAL, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10, 4, 0, 47, 0, 0, 100, "rat")); + push_back(MonsterStruct("Morgana", 200000, 300, 35, 100, 1, CLASS_15, 2, 60, + DT_ENERGY, SA_PARALYZE, 1, 1, MONSTER_HUMANOID, 50, 50, + 50, 50, 100, 80, 0, 0, 0, 100, 6, 0, 50, 0, 10, 100, + "disint")); + push_back(MonsterStruct("Master Thief", 20000, 100, 20, 50, 1, CLASS_ROBBER, 1, + 250, DT_PHYSICAL, SA_NONE, 40, 0, MONSTER_HUMANOID, 0, + 0, 0, 0, 0, 0, 0, 0, 250, 20, 4, 0, 54, 0, 14, 100, + "thief")); + push_back(MonsterStruct("Royal Vampire", 400000, 750, 40, 125, 1, CLASS_CLERIC, + 10, 50, DT_PHYSICAL, SA_CURSEITEM, 120, 0, + MONSTER_UNDEAD, 50, 50, 50, 50, 50, 50, 65, 0, 0, 0, 0, + 0, 57, 0, 0, 100, "vamp")); + push_back(MonsterStruct("Ct. Blackfang", 2000000, 1500, 50, 150, 1, + CLASS_CLERIC, 10, 100, DT_PHYSICAL, SA_DEATH, 120, 0, + MONSTER_UNDEAD, 75, 75, 75, 75, 75, 75, 75, 0, 0, 0, 0, + 0, 58, 0, 10, 100, "vamp")); + push_back(MonsterStruct("Troll Guard", 15000, 200, 10, 60, 1, CLASS_16, 2, 35, + DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 50, 50, 50, + 50, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 100, "troll")); + push_back(MonsterStruct("Troll Chief", 20000, 300, 15, 65, 1, CLASS_16, 2, 50, + DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 50, 50, 50, + 50, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 100, "troll")); + push_back(MonsterStruct("Hobstadt", 25000, 400, 20, 70, 1, CLASS_16, 2, 50, + DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 50, 50, 50, + 50, 0, 0, 0, 0, 1000, 0, 4, 0, 56, 0, 0, 100, "troll")); + push_back(MonsterStruct("Graalg", 20000, 200, 15, 50, 1, CLASS_16, 5, 10, + DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 0, 0, 0, 0, 0, + 0, 0, 0, 1000, 0, 5, 0, 42, 0, 0, 100, "ogre")); + push_back(MonsterStruct("Vampire King", 3000000, 10000, 60, 200, 1, + CLASS_CLERIC, 10, 250, DT_PHYSICAL, SA_ERADICATE, 150, + 0, MONSTER_UNDEAD, 80, 80, 80, 80, 80, 80, 90, 0, 0, 0, + 0, 0, 58, 0, 0, 100, "vamp")); + push_back(MonsterStruct("Valio", 60000, 150, 15, 60, 1, CLASS_PALADIN, 10, 25, + DT_1, SA_NONE, 1, 0, MONSTER_HUMANOID, 50, 30, 30, 30, + 40, 30, 0, 0, 0, 0, 0, 0, 65, 0, 0, 100, "wizard")); + push_back(MonsterStruct("Sky Golem", 200000, 1000, 50, 100, 1, CLASS_15, 2, + 100, DT_COLD, SA_NONE, 1, 1, MONSTER_GOLEM, 50, 50, + 100, 50, 50, 50, 50, 0, 0, 0, 0, 1, 24, 0, 0, 100, + "golem")); + push_back(MonsterStruct("Gurodel", 100000, 750, 30, 60, 2, CLASS_16, 100, 6, + DT_PHYSICAL, SA_UNCONSCIOUS, 110, 0, MONSTER_0, 0, 0, + 0, 0, 0, 0, 0, 0, 5000, 0, 6, 0, 22, 0, 0, 100, + "giant")); + push_back(MonsterStruct("Yog", 25000, 100, 5, 60, 1, CLASS_SORCERER, 1, 30, + DT_PHYSICAL, SA_NONE, 25, 0, MONSTER_HUMANOID, 0, 0, + 0, 0, 0, 0, 0, 0, 200, 0, 4, 0, 6, 0, 10, 100, + "barbarch")); + push_back(MonsterStruct("Sharla", 10000, 50, 5, 50, 1, CLASS_RANGER, 3, 4, + DT_PHYSICAL, SA_NONE, 20, 0, MONSTER_0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 53, 0, 0, 100, "hiss")); + push_back(MonsterStruct("Ghost Mummy", 500000, 500, 35, 175, 1, CLASS_CLERIC, + 200, 5, DT_PHYSICAL, SA_AGING, 150, 0, MONSTER_UNDEAD, + 0, 60, 80, 80, 80, 50, 80, 0, 0, 0, 0, 0, 40, 0, 6, + 100, "orc")); + push_back(MonsterStruct("Phase Mummy", 500000, 500, 35, 175, 1, CLASS_CLERIC, + 200, 6, DT_PHYSICAL, SA_DRAINSP, 150, 0, + MONSTER_UNDEAD, 0, 70, 80, 80, 80, 60, 85, 0, 0, 0, 0, + 0, 39, 0, 7, 100, "mummy")); + push_back(MonsterStruct("Xenoc", 250000, 700, 35, 175, 1, CLASS_15, 10, 50, + DT_ENERGY, SA_NONE, 1, 0, MONSTER_HUMANOID, 50, 50, 50, + 50, 100, 50, 0, 0, 0, 100, 6, 0, 64, 0, 0, 100, + "boltelec")); + push_back(MonsterStruct("Barkman", 4000000, 40000, 25, 100, 3, CLASS_16, 250, + 1, DT_FIRE, SA_NONE, 1, 0, MONSTER_0, 100, 50, 0, 100, + 0, 0, 0, 0, 0, 0, 6, 0, 19, 0, 11, 100, "fire")); +} + +void MonsterData::load(const Common::String &name) { + File f(name); + synchronize(f); +} + +void MonsterData::synchronize(Common::SeekableReadStream &s) { + clear(); + + MonsterData spr; + while (!s.eos()) { + spr.synchronize(s); + push_back(spr); + } +} + +/*------------------------------------------------------------------------*/ + +SurroundingMazes::SurroundingMazes() { + _north = 0; + _east = 0; + _south = 0; + _west = 0; +} + +void SurroundingMazes::synchronize(Common::SeekableReadStream &s) { + _north = s.readUint16LE(); + _east = s.readUint16LE(); + _south = s.readUint16LE(); + _west = s.readUint16LE(); +} + +/*------------------------------------------------------------------------*/ + +MazeDifficulties::MazeDifficulties() { + _unlockDoor = 0; + _unlockBox = 0; + _bashDoor = 0; + _bashGrate = 0; + _bashWall = 0; +} + +void MazeDifficulties::synchronize(Common::SeekableReadStream &s) { + _wallNoPass = s.readByte(); + _surfaceNoPass = s.readByte(); + _unlockDoor = s.readByte(); + _unlockBox = s.readByte(); + _bashDoor = s.readByte(); + _bashGrate = s.readByte(); + _bashWall = s.readByte(); + _chance2Run = s.readByte(); +} + +/*------------------------------------------------------------------------*/ + +MazeData::MazeData() { + for (int y = 0; y < MAP_HEIGHT; ++y) { + Common::fill(&_wallData[y][0], &_wallData[y][MAP_WIDTH], 0); + Common::fill(&_cellFlag[y][0], &_cellFlag[y][MAP_WIDTH], 0); + Common::fill(&_seenTiles[y][0], &_seenTiles[y][MAP_WIDTH], 0); + Common::fill(&_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH], 0); + _wallTypes[y] = 0; + _surfaceTypes[y] = 0; + } + _mazeNumber = 0; + _mazeFlags = _mazeFlags2 = 0; + _floorType = 0; + _trapDamage = 0; + _wallKind = 0; + _tavernTips = 0; +} + +void MazeData::synchronize(Common::SeekableReadStream &s) { + for (int y = 0; y < MAP_HEIGHT; ++y) { + for (int x = 0; x < MAP_WIDTH; ++x) + _wallData[y][x] = s.readUint16LE(); + } + for (int y = 0; y < MAP_HEIGHT; ++y) { + for (int x = 0; x < MAP_WIDTH; ++x) + _cellFlag[y][x] = s.readByte(); + } + + _mazeNumber = s.readUint16LE(); + _surroundingMazes.synchronize(s); + _mazeFlags = s.readUint16LE(); + _mazeFlags2 = s.readUint16LE(); + + for (int i = 0; i < 16; ++i) + _wallTypes[i] = s.readByte(); + for (int i = 0; i < 16; ++i) + _surfaceTypes[i] = s.readByte(); + + _floorType = s.readByte(); + _runPosition.x = s.readByte(); + _difficulties.synchronize(s); + _runPosition.y = s.readByte(); + _trapDamage = s.readByte(); + _wallKind = s.readByte(); + _tavernTips = s.readByte(); + + Common::Serializer ser(&s, nullptr); + for (int y = 0; y < MAP_HEIGHT; ++y) + SavesManager::syncBitFlags(ser, &_seenTiles[y][0], &_seenTiles[y][MAP_WIDTH]); + for (int y = 0; y < MAP_HEIGHT; ++y) + SavesManager::syncBitFlags(ser, &_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH]); +} + +/** + * Flags all tiles for the map as having been stepped on + */ +void MazeData::setAllTilesStepped() { + for (int y = 0; y < MAP_HEIGHT; ++y) + Common::fill(&_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH], true); +} + +void MazeData::clearCellBits() { + for (int y = 0; y < MAP_HEIGHT; ++y) { + for (int x = 0; x < MAP_WIDTH; ++x) + _cellFlag[y][x] &= 0xF8; + } +} + +/*------------------------------------------------------------------------*/ + +MobStruct::MobStruct() { + _id = 0; + _direction = DIR_NORTH; +} + +bool MobStruct::synchronize(Common::SeekableReadStream &s) { + _pos.x = (int8)s.readByte(); + _pos.y = (int8)s.readByte(); + _id = s.readByte(); + _direction = (Direction)s.readByte(); + + return _id != 0xff || _pos.x != -1 || _pos.y != -1; +} + +/*------------------------------------------------------------------------*/ + +MonsterObjectData::MonsterObjectData(XeenEngine *vm): _vm(vm) { +} + +void MonsterObjectData::synchronize(Common::SeekableReadStream &s, + bool isOutdoors, MonsterData monsterData) { + _objects.clear(); + _monsters.clear(); + _wallPicIds.clear(); + _wallImages.clear(); + Common::Array<int> objectSprites; + Common::Array<int> monsterIds; + Common::Array<MobStruct> objData; + Common::Array<MobStruct> monData; + byte b; + + for (int i = 0; i < 16; ++i) { + if ((b = s.readByte()) != 0xff) + objectSprites.push_back(b); + } + for (int i = 0; i < 16; ++i) { + if ((b = s.readByte()) != 0xff) + monsterIds.push_back(b); + } + for (int i = 0; i < 16; ++i) { + if ((b = s.readByte()) != 0xff) + _wallPicIds.push_back(b); + } + + MobStruct mobStruct; + while (mobStruct.synchronize(s)) + objData.push_back(mobStruct); + while (mobStruct.synchronize(s)) + monData.push_back(mobStruct); + if (!isOutdoors) { + while (mobStruct.synchronize(s)) + _wallImages.push_back(mobStruct); + } + + // Merge up objects + _objects.resize(objData.size()); + for (uint i = 0; i < objData.size(); ++i) { + MazeObject &dest = _objects[i]; + dest._position = objData[i]._pos; + dest._number = objData[i]._id; + dest._id = objectSprites[dest._number]; + dest._direction = objData[i]._direction; + dest._frame = 100; + } + + // merge up monsters + for (uint i = 0; i < monData.size(); ++i) { + MazeMonster &dest = _monsters[i]; + dest._position = monData[i]._pos; + dest._id = monData[i]._id; + dest._refId = monsterIds[dest._id]; + + MonsterStruct &mon = monsterData[dest._refId]; + dest._hp = mon._hp; + dest._frame = _vm->getRandomNumber(7); + dest._effect1 = dest._effect2 = mon._animationEffect; + if (mon._animationEffect) + dest._effect3 = _vm->getRandomNumber(7); + } +} + +/*------------------------------------------------------------------------*/ + +HeadData::HeadData() { + for (int y = 0; y < MAP_HEIGHT; ++y) { + for (int x = 0; x < MAP_WIDTH; ++x) { + _data[y][x]._left = _data[y][x]._right = 0; + } + } +} + +void HeadData::synchronize(Common::SeekableReadStream &s) { + for (int y = 0; y < MAP_HEIGHT; ++y) { + for (int x = 0; x < MAP_WIDTH; ++x) { + _data[y][x]._left = s.readByte(); + _data[y][x]._right = s.readByte(); + } + } +} + +/*------------------------------------------------------------------------*/ + +Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { + _townPortalSide = 0; + _sideObj = 0; + _sideMon = 0; + _isOutdoors = false; +} + +void Map::load(int mapId) { + Screen &screen = *_vm->_screen; + if (_vm->_falling) { + Window &w = screen._windows[9]; + w.open(); + w.writeString(OOPS); + } else { + PleaseWait::show(_vm); + } + + if (mapId >= 113 && mapId <= 127) { + _townPortalSide = 0; + } else { + _townPortalSide = _vm->_loadDarkSide; + } + + if (_vm->getGameID() == GType_WorldOfXeen) { + if (_vm->_loadDarkSide) { + _objPicSprites.load("clouds.dat"); + _monsterData.load("xeen.mon"); + _wallPicSprites.load("xeenpic.dat"); + } else { + switch (mapId) { + case 113: + case 114: + case 115: + case 116: + case 128: + _objPicSprites.load("clouds.dat"); + _monsterData.load("dark.mon"); + _wallPicSprites.load("darkpic.dat"); + _sideObj = 0; + break; + case 117: + case 118: + case 119: + case 120: + case 124: + _objPicSprites.load("clouds.dat"); + _monsterData.load("xeen.mon"); + _wallPicSprites.load("darkpic.dat"); + _sideObj = 0; + _sideMon = 0; + break; + case 125: + case 126: + case 127: + _objPicSprites.load("clouds.dat"); + _monsterData.load("dark.mon"); + _wallPicSprites.load("xeenpic.dat"); + break; + default: + _objPicSprites.load("dark.dat"); + _monsterData.load("ddark.mon"); + _wallPicSprites.load("darkpic.dat"); + break; + } + } + } + + bool isDarkCc = _vm->getGameID() == GType_DarkSide; + uint16 mapGrid[9]; + uint16 *gridPtr = &mapGrid[0]; + bool textLoaded = false; + + // Iterate through loading the given maze as well as the two successive + // mazes in each of the four cardinal directions + for (int idx = 0; idx < 9; ++idx, ++gridPtr) { + if (mapId != 0) { + // Load in the maze's data file + Common::String datName = Common::String::format("maze%c%03u.dat", + (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); + File datFile(datName); + _mazeData.synchronize(datFile); + datFile.close(); + + if (isDarkCc && mapId == 50) + _mazeData.setAllTilesStepped(); + if (!isDarkCc && _vm->_party._gameFlags[25] && + (mapId == 42 || mapId == 43 || mapId == 4)) { + _mazeData.clearCellBits(); + } + + _isOutdoors = (_mazeData._mazeFlags2 & FLAG_IS_OUTDOORS) != 0; + + // Handle loading text data + if (!textLoaded) { + textLoaded = true; + Common::String txtName = Common::String::format("%s%c%03u.txt", + isDarkCc ? "dark" : "xeen", mapId >= 100 ? 'x' : '0'); + File fText(txtName); + char mazeName[33]; + fText.read(mazeName, 33); + mazeName[32] = '\0'; + + _mazeName = Common::String(mazeName); + fText.close(); + + // Load the monster data + Common::String mobName = Common::String::format("maze%c%03u.mob", + (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); + File mobFile(mobName); + _mobData.synchronize(mobFile, _isOutdoors, _monsterData); + mobFile.close(); + + Common::String headName = Common::String::format("aaze%c%03u.hed", + (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); + File headFile(headName); + _headData.synchronize(headFile); + headFile.close(); + + if (!isDarkCc && _vm->_party._mazeId) + _mobData._monsters.clear(); + + if (!isDarkCc && mapId == 15) { + if ((_mobData._monsters[0]._position.x > 31 || _mobData._monsters[0]._position.y > 31) && + (_mobData._monsters[1]._position.x > 31 || _mobData._monsters[1]._position.y > 31) && + (_mobData._monsters[2]._position.x > 31 || _mobData._monsters[2]._position.y > 31)) { + _vm->_party._gameFlags[56] = true; + } + } + } + } + + // TODO: Move to next surrounding maze + } + + // TODO +} + +} // End of namespace Xeen diff --git a/engines/xeen/map.h b/engines/xeen/map.h new file mode 100644 index 0000000000..4482173642 --- /dev/null +++ b/engines/xeen/map.h @@ -0,0 +1,264 @@ +/* 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 XEEN_MAP_H +#define XEEN_MAP_H + +#include "common/stream.h" +#include "common/rect.h" +#include "xeen/party.h" +#include "xeen/sprites.h" + +namespace Xeen { + +#define MAP_WIDTH 16 +#define MAP_HEIGHT 16 + +class XeenEngine; + +enum DamageType { + DT_PHYSICAL = 0, DT_1 = 1, DT_FIRE = 2, DT_ELECTRICAL = 3, + DT_COLD = 4, DT_POISON = 5, DT_ENERGY = 6, DT_SLEEP = 7, + DT_FINGEROFDEATH = 8, DT_HOLYWORD = 9, DT_MASS_DISTORTION = 10, + DT_UNDED = 11, DT_BEASTMASTER = 12, DT_DRAGONSLEEP = 13, + DT_GOLEMSTOPPER = 14, DT_HYPNOTIZE = 15, DT_INSECT_SPRAY = 16, + DT_POISON_VALLEY = 17, DT_MAGIC_ARROW = 18 +}; + +enum SpecialAttack { + SA_NONE = 0, SA_MAGIC = 1, SA_FIRE = 2, SA_ELEC = 3, SA_COLD = 4, + SA_POISON = 5, SA_ENERGY = 6, SA_DISEASE = 7, SA_INSANE = 8, + SA_SLEEP = 9, SA_CURSEITEM = 10, SA_INLOVE = 11, SA_DRAINSP = 12, + SA_CURSE = 13, SA_PARALYZE = 14, SA_UNCONSCIOUS = 15, + SA_CONFUSE = 16, SA_BREAKWEAPON = 17, SA_WEAKEN = 18, + SA_ERADICATE = 19, SA_AGING = 20, SA_DEATH = 21, SA_STONE = 22 +}; + +enum MonsterType { + MONSTER_0 = 0, MONSTER_ANIMAL = 1, MONSTER_INSECT = 2, + MONSTER_HUMANOID = 3, MONSTER_UNDEAD = 4, MONSTER_GOLEM = 5, + MONSTER_DRAGON = 6 +}; + +class MonsterStruct { +public: + Common::String _name; + int _experience; + int _hp; + int _accuracy; + int _speed; + int _numberOfAttacks; + CharacterClass _hatesClass; + int _strikes; + int _dmgPerStrike; + DamageType _attackType; + SpecialAttack _specialAttack; + int _hitChance; + int _rangeAttack; + MonsterType _monsterType; + int _fireResistence; + int _electricityResistence; + int _coldResistence; + int _poisonResistence; + int _energyResistence; + int _magicResistence; + int _phsyicalResistence; + int _field29; + int _gold; + int _gems; + int _itemDrop; + int _flying; + int _imageNumber; + int _loopAnimation; + int _animationEffect; + int _field32; + Common::String _attackVoc; +public: + MonsterStruct(); + MonsterStruct(Common::String name, int experience, int hp, int accuracy, + int speed, int numberOfAttacks, CharacterClass hatesClass, int strikes, + int dmgPerStrike, DamageType attackType, SpecialAttack specialAttack, + int hitChance, int rangeAttack, MonsterType monsterType, + int fireResistence, int electricityResistence, int coldResistence, + int poisonResistence, int energyResistence, int magicResistence, + int phsyicalResistence, int field29, int gold, int gems, int itemDrop, + int flying, int imageNumber, int loopAnimation, int animationEffect, + int field32, Common::String attackVoc); + + void synchronize(Common::SeekableReadStream &s); +}; + +class MonsterData : public Common::Array<MonsterStruct> { +private: + void synchronize(Common::SeekableReadStream &s); +public: + MonsterData(); + + void load(const Common::String &name); +}; + +class SurroundingMazes { +public: + int _north; + int _east; + int _south; + int _west; +public: + SurroundingMazes(); + + void synchronize(Common::SeekableReadStream &s); +}; + +class MazeDifficulties { +public: + int _wallNoPass; + int _surfaceNoPass; + int _unlockDoor; + int _unlockBox; + int _bashDoor; + int _bashGrate; + int _bashWall; + int _chance2Run; +public: + MazeDifficulties(); + + void synchronize(Common::SeekableReadStream &s); +}; + +enum MazeFlags { + OUTFLAG_GRATE = 0x80, OUTFLAG_DRAIN = 0x20, OUTFLAG_OBJECT_EXISTS = 0x08, + INFLAG_INSIDE = 0x08, + FLAG_WATER = 0x40, FLAG_AUTOEXECUTE_EVENT = 0x10, + FLAG_GROUND_BITS = 7 +}; + +enum MazeFlags2 { FLAG_IS_OUTDOORS = 0x8000, FLAG_IS_DARK = 0x4000 }; + +class MazeData { +public: + int _wallData[MAP_HEIGHT][MAP_WIDTH]; + int _cellFlag[MAP_HEIGHT][MAP_WIDTH]; + int _mazeNumber; + SurroundingMazes _surroundingMazes; + int _mazeFlags; + int _mazeFlags2; + int _wallTypes[16]; + int _surfaceTypes[16]; + int _floorType; + Common::Point _runPosition; + MazeDifficulties _difficulties; + int _trapDamage; + int _wallKind; + int _tavernTips; + bool _seenTiles[MAP_HEIGHT][MAP_WIDTH]; + bool _steppedOnTiles[MAP_HEIGHT][MAP_WIDTH]; +public: + MazeData(); + + void synchronize(Common::SeekableReadStream &s); + + void setAllTilesStepped(); + + void clearCellBits(); +}; + +class MobStruct { +public: + Common::Point _pos; + int _id; + Direction _direction; +public: + MobStruct(); + + bool synchronize(Common::SeekableReadStream &s); +}; + +struct MazeObject { + Common::Point _position; + int _number; + int _frame; + int _id; + Direction _direction; + bool _flipped; +}; + +struct MazeMonster { + Common::Point _position; + int _frame; + int _id; + int _refId; + int _hp; + int _effect1, _effect2; + int _effect3; +}; + +class MonsterObjectData { +private: + XeenEngine *_vm; +public: + Common::Array<MazeObject> _objects; + Common::Array<MazeMonster> _monsters; + Common::Array<int> _wallPicIds; + Common::Array<MobStruct> _wallImages; +public: + MonsterObjectData(XeenEngine *vm); + + void synchronize(Common::SeekableReadStream &s, bool isOutdoors, + MonsterData monsterData); +}; + +class HeadData { +public: + struct HeadEntry { + int _left; + int _right; + }; + HeadEntry _data[MAP_HEIGHT][MAP_WIDTH]; +public: + HeadData(); + + void synchronize(Common::SeekableReadStream &s); +}; + +class Map { +private: + XeenEngine *_vm; + MazeData _mazeData; + Common::String _mazeName; + MonsterObjectData _mobData; + HeadData _headData; + SpriteResource _objPicSprites; + MonsterData _monsterData; + SpriteResource _wallPicSprites; + int _townPortalSide; + int _sideObj; + int _sideMon; + bool _isOutdoors; +public: + Map(XeenEngine *vm); + + void load(int mapId); +}; + +} // End of namespace Xeen + +#endif /* XEEN_MAP_H */ diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 7f0caf7b10..5cbb1bb064 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -7,12 +7,14 @@ MODULE_OBJS := \ debugger.o \ detection.o \ dialogs.o \ + dialogs_error.o \ dialogs_options.o \ events.o \ files.o \ font.o \ interface.o \ items.o \ + map.o \ party.o \ resdata.o \ resources.o \ diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 25366d52ed..ec25f4a71c 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -44,7 +44,7 @@ PlayerStruct::PlayerStruct() { _sex = MALE; _race = HUMAN; _xeenSide = 0; - _class = KNIGHT; + _class = CLASS_KNIGHT; _ACTemp = 0; _dbDay = 0; _tempAge = 0; @@ -302,7 +302,7 @@ void Party::synchronize(Common::Serializer &s) { bool Party::checkSkill(Skill skillId) { uint total = 0; for (uint i = 0; i < _activeParty.size(); ++i) { - if (_activeParty[i]->_skills[skillId]) { + if (_activeParty[i]._skills[skillId]) { ++total; switch (skillId) { @@ -324,6 +324,8 @@ bool Party::checkSkill(Skill skillId) { } } } + + return false; } bool Party::isInParty(int charId) { @@ -335,4 +337,10 @@ bool Party::isInParty(int charId) { return false; } +void Party::copyPartyToRoster(Roster &r) { + for (int i = 0; i < _partyCount; ++i) { + r[_partyMembers[i]] = _activeParty[i]; + } +} + } // End of namespace Xeen diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 7e5010427f..b415707344 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -39,8 +39,11 @@ enum Sex { MALE = 0, FEMALE = 1, YES_PLEASE = 2 }; enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 }; -enum CharacterClass { KNIGHT = 0, PALADIN = 1, ARCHER = 2, CLERIC = 3, - SORCERER = 4, ROBBER = 5, NINJA = 6, BARBARIAN = 7, DRUID = 8, RANGER = 9 +enum CharacterClass { + CLASS_KNIGHT = 0, CLASS_PALADIN = 1, CLASS_ARCHER = 2, CLASS_CLERIC = 3, + CLASS_SORCERER = 4, CLASS_ROBBER = 5, CLASS_NINJA = 6, CLASS_BARBARIAN = 7, + CLASS_DRUID = 8, CLASS_RANGER = 9, + CLASS_12 = 12, CLASS_15 = 15, CLASS_16 = 16 }; enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3, @@ -195,7 +198,7 @@ public: bool _characterFlags[30][24]; public: // Other party related runtime data - Common::Array<PlayerStruct *> _activeParty; + Common::Array<PlayerStruct> _activeParty; int _combatPartyCount; public: Party(); @@ -205,6 +208,8 @@ public: bool checkSkill(Skill skillId); bool isInParty(int charId); + + void copyPartyToRoster(Roster &r); }; } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 79e8ba183c..3f59f3e1c9 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -279,4 +279,28 @@ const int CHAR_FACES_X[6] = { 10, 45, 81, 117, 153, 189 }; const int HP_BARS_X[6] = { 13, 50, 86, 122, 158, 194 }; +const char *const NO_ONE_TO_ADVENTURE_WITH = "You have no one to adventure with"; + +const char *const YOUR_ROSTER_IS_FULL = "Your Roster is full!"; + +const byte BACKGROUND_XLAT[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF7, 0xFF, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF9, 0xFF, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF7, 0xFF, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF5, 0xFF, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF3, 0xFF, 0x0D, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + +const char *const PLEASE_WAIT = "\014""d\003""c\011""000" + "\013""002Please Wait..."; + +const char *const OOPS = "\003""c\011""000\013""002Oops..."; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 80febec9b4..78104b233c 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -58,6 +58,16 @@ extern const int CHAR_FACES_X[6]; extern const int HP_BARS_X[6]; +extern const char *const NO_ONE_TO_ADVENTURE_WITH; + +extern const byte BACKGROUND_XLAT[]; + +extern const char *const YOUR_ROSTER_IS_FULL; + +extern const char *const PLEASE_WAIT; + +extern const char *const OOPS; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index 7482a12ff5..95957c4daa 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -75,4 +75,12 @@ void SavesManager::reset() { delete pty; } +void SavesManager::readCharFile() { + warning("TODO: readCharFile"); +} + +void SavesManager::writeCharFile() { + warning("TODO: writeCharFile"); +} + } // End of namespace Xeen diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h index f3ace80a03..1e67638fe4 100644 --- a/engines/xeen/saves.h +++ b/engines/xeen/saves.h @@ -49,6 +49,10 @@ public: public: SavesManager(XeenEngine *vm, Party &party, Roster &roster); void reset(); + + void readCharFile(); + + void writeCharFile(); }; } // End of namespace Xeen diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index ba2c97b267..cfde7804ae 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -166,10 +166,10 @@ void Window::writeString(const Common::String &s) { _vm->_screen->writeString(s, _innerBounds); } -void Window::drawList(DrawStruct *items) { +void Window::drawList(DrawStruct *items, int count) { Screen &screen = *_vm->_screen; - for (; items->_sprites != nullptr; ++items) { + for (int i = 0; i < count; ++i, ++items) { if (items->_frame == -1 || items->_scale == -1) continue; diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index ae38ec3a03..1e164a3166 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -90,7 +90,7 @@ public: void writeString(const Common::String &s); - void drawList(DrawStruct *items); + void drawList(DrawStruct *items, int count); }; class Screen: public FontSurface { diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 5b8fe5266a..598870dc57 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -39,6 +39,10 @@ SpriteResource::SpriteResource(const Common::String &filename) { load(filename); } +SpriteResource::~SpriteResource() { + clear(); +} + void SpriteResource::load(const Common::String &filename) { // Open the resource File f(filename); @@ -60,8 +64,10 @@ void SpriteResource::load(const Common::String &filename) { } } -SpriteResource::~SpriteResource() { +void SpriteResource::clear() { delete[] _data; + _data = nullptr; + _filesize = 0; } void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const { diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index e9cdf721eb..998d5d3e79 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -51,6 +51,8 @@ public: void load(const Common::String &filename); + void clear(); + void draw(XSurface &dest, int frame, const Common::Point &destPos) const; void draw(XSurface &dest, int frame) const; diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 1574871c25..b3ac7433a3 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -38,7 +38,9 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), _randomSource("Xeen") { _debugger = nullptr; _events = nullptr; + _files = nullptr; _interface = nullptr; + _map = nullptr; _saves = nullptr; _screen = nullptr; _sound = nullptr; @@ -49,16 +51,19 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _face1State = 0; _face2State = 0; _noDirectionSense = false; + _falling = false; } XeenEngine::~XeenEngine() { delete _debugger; delete _events; delete _interface; + delete _map; delete _saves; delete _screen; delete _sound; delete _eventData; + delete _files; } void XeenEngine::initialize() { @@ -69,10 +74,11 @@ void XeenEngine::initialize() { DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling"); // Create sub-objects of the engine - FileManager::init(this); + _files = new FileManager(this); _debugger = new Debugger(this); _events = new EventsManager(this); _interface = new Interface(this); + _map = new Map(this); _saves = new SavesManager(this, _party, _roster); _screen = new Screen(this); _screen->setupWindows(); @@ -249,9 +255,34 @@ void XeenEngine::showMainMenu() { //OptionsMenu::show(this); } +/** + * Main method for playing the game + */ void XeenEngine::playGame() { _saves->reset(); - _interface->setup(true); + play(); +} + +/* + * Secondary method for handling the actual gameplay + */ +void XeenEngine::play() { + // TODO: Init variables + + _screen->loadBackground("back.raw"); + _screen->loadPalette("mm4.pal"); + _interface->loadCharIcons(_party._partyCount); + _iconsSprites.load("main.icn"); + + if (getGameID() != GType_WorldOfXeen && !_loadDarkSide) { + _loadDarkSide = true; + _party._mazeId = 29; + _party._mazeDirection = DIR_NORTH; + _party._mazePosition.x = 25; + _party._mazePosition.y = 21; + } + + _map->load(_party._mazeId); } } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index a7210ca871..9938519b9b 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -34,7 +34,9 @@ #include "xeen/debugger.h" #include "xeen/dialogs.h" #include "xeen/events.h" +#include "xeen/files.h" #include "xeen/interface.h" +#include "xeen/map.h" #include "xeen/party.h" #include "xeen/saves.h" #include "xeen/screen.h" @@ -77,7 +79,8 @@ enum Mode { MODE_6 = 6, MODE_7 = 7, MODE_8 = 8, - MODE_9 = 9 + MODE_9 = 9, + MODE_17 = 17 }; struct XeenGameDescription; @@ -90,10 +93,15 @@ private: const XeenGameDescription *_gameDescription; Common::RandomSource _randomSource; int _loadSaveSlot; + SpriteResource _iconsSprites; void showIntro(); void showMainMenu(); + + void play(); + + void pleaseWait(); protected: /** * Play the game @@ -119,7 +127,9 @@ private: public: Debugger *_debugger; EventsManager *_events; + FileManager *_files; Interface *_interface; + Map *_map; SavesManager *_saves; Screen *_screen; SoundManager *_sound; @@ -134,6 +144,7 @@ public: int _face1State; int _face2State; bool _noDirectionSense; + bool _falling; public: XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); virtual ~XeenEngine(); -- cgit v1.2.3 From 86cdb68f4da1f43412bbbadca1e2c4a9a80c60d8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 5 Jan 2015 11:02:35 -0500 Subject: XEEN: Properly implemented map loading first loading loop --- engines/xeen/map.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++--------- engines/xeen/map.h | 8 +++++++- 2 files changed, 54 insertions(+), 10 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index d797179e15..4a3eda6b11 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -29,6 +29,14 @@ namespace Xeen { +const int MAP_GRID_PRIOR_INDEX[] = { 0, 0, 0, 0, 1, 2, 3, 4, 0 }; + +const int MAP_GRID_PRIOR_DIRECTION[] = { 0, 1, 2, 3, 1, 2, 3, 0, 0 }; + +const int MAP_GRID_PRIOR_INDEX2[] = { 0, 0, 0, 0, 2, 3, 4, 1, 0 }; + +const int MAP_GRID_PRIOR_DIRECTION2[] = { 0, 1, 2, 3, 0, 1, 2, 3, 0 }; + MonsterStruct::MonsterStruct() { _experience = 0; _hp = 0; @@ -490,6 +498,19 @@ void SurroundingMazes::synchronize(Common::SeekableReadStream &s) { _west = s.readUint16LE(); } +int &SurroundingMazes::operator[](int idx) { + switch (idx) { + case DIR_NORTH: + return _north; + case DIR_EAST: + return _east; + case DIR_SOUTH: + return _south; + default: + return _west; + } +} + /*------------------------------------------------------------------------*/ MazeDifficulties::MazeDifficulties() { @@ -752,29 +773,30 @@ void Map::load(int mapId) { } bool isDarkCc = _vm->getGameID() == GType_DarkSide; - uint16 mapGrid[9]; - uint16 *gridPtr = &mapGrid[0]; + MazeData *mazeData = &_mazeData[0]; bool textLoaded = false; // Iterate through loading the given maze as well as the two successive // mazes in each of the four cardinal directions - for (int idx = 0; idx < 9; ++idx, ++gridPtr) { + for (int idx = 0; idx < 9; ++idx, ++mazeData) { + mazeData->_mazeId = mapId; + if (mapId != 0) { // Load in the maze's data file Common::String datName = Common::String::format("maze%c%03u.dat", (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); File datFile(datName); - _mazeData.synchronize(datFile); + mazeData->synchronize(datFile); datFile.close(); if (isDarkCc && mapId == 50) - _mazeData.setAllTilesStepped(); + mazeData->setAllTilesStepped(); if (!isDarkCc && _vm->_party._gameFlags[25] && (mapId == 42 || mapId == 43 || mapId == 4)) { - _mazeData.clearCellBits(); + mazeData->clearCellBits(); } - _isOutdoors = (_mazeData._mazeFlags2 & FLAG_IS_OUTDOORS) != 0; + _isOutdoors = (mazeData->_mazeFlags2 & FLAG_IS_OUTDOORS) != 0; // Handle loading text data if (!textLoaded) { @@ -815,10 +837,26 @@ void Map::load(int mapId) { } } - // TODO: Move to next surrounding maze + // Move to next surrounding maze + MazeData *baseMaze = &_mazeData[MAP_GRID_PRIOR_INDEX[idx]]; + mapId = baseMaze->_surroundingMazes[MAP_GRID_PRIOR_DIRECTION[idx]]; + if (mapId) { + baseMaze = &_mazeData[MAP_GRID_PRIOR_INDEX2[idx]]; + mapId = baseMaze->_surroundingMazes[MAP_GRID_PRIOR_DIRECTION2[idx]]; + } } - // TODO + // TODO: Switch setting flags that don't seem to ever be used + + // Reload object data, since prior loop iterations replaced the data + // for the main map with all the surrounding mazes + Common::String mobName = Common::String::format("maze%c%03u.mob", + (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); + File mobFile(mobName); + _mobData.synchronize(mobFile, _isOutdoors, _monsterData); + mobFile.close(); + + // TODO: Loop loading moer data } } // End of namespace Xeen diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 4482173642..e52e978106 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -126,6 +126,8 @@ public: SurroundingMazes(); void synchronize(Common::SeekableReadStream &s); + + int &operator[](int idx); }; class MazeDifficulties { @@ -155,6 +157,7 @@ enum MazeFlags2 { FLAG_IS_OUTDOORS = 0x8000, FLAG_IS_DARK = 0x4000 }; class MazeData { public: + // Resource fields int _wallData[MAP_HEIGHT][MAP_WIDTH]; int _cellFlag[MAP_HEIGHT][MAP_WIDTH]; int _mazeNumber; @@ -171,6 +174,9 @@ public: int _tavernTips; bool _seenTiles[MAP_HEIGHT][MAP_WIDTH]; bool _steppedOnTiles[MAP_HEIGHT][MAP_WIDTH]; + + // Misc fields + int _mazeId; public: MazeData(); @@ -242,7 +248,7 @@ public: class Map { private: XeenEngine *_vm; - MazeData _mazeData; + MazeData _mazeData[9]; Common::String _mazeName; MonsterObjectData _mobData; HeadData _headData; -- cgit v1.2.3 From 42165d21bb626e325d79d755bbf65b8b5044020f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 5 Jan 2015 15:10:42 -0500 Subject: XEEN: Implement more map loading --- engines/xeen/interface.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++---- engines/xeen/interface.h | 22 +++++++++++- engines/xeen/map.cpp | 16 +++++++-- engines/xeen/map.h | 2 ++ engines/xeen/screen.h | 4 +-- engines/xeen/xeen.cpp | 27 ++++++++++++-- engines/xeen/xeen.h | 3 +- 7 files changed, 149 insertions(+), 15 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 08128e54f0..4f40c4730d 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -44,10 +44,31 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); _intrIndex1 = 0; - _faceDrawStructs[0] = DrawStruct(nullptr, 0, 0, 0); - _faceDrawStructs[1] = DrawStruct(nullptr, 0, 101, 0); - _faceDrawStructs[2] = DrawStruct(nullptr, 0, 0, 43); - _faceDrawStructs[3] = DrawStruct(nullptr, 0, 101, 43); + initDrawStructs(); +} + +void Interface::initDrawStructs() { + _faceDrawStructs[0] = DrawStruct(0, 0, 0); + _faceDrawStructs[1] = DrawStruct(0, 101, 0); + _faceDrawStructs[2] = DrawStruct(0, 0, 43); + _faceDrawStructs[3] = DrawStruct(0, 101, 43); + + _mainList[0] = DrawStruct(7, 232, 74); + _mainList[1] = DrawStruct(0, 235, 75); + _mainList[2] = DrawStruct(2, 260, 75); + _mainList[3] = DrawStruct(4, 286, 75); + _mainList[4] = DrawStruct(6, 235, 96); + _mainList[5] = DrawStruct(8, 260, 96); + _mainList[6] = DrawStruct(10, 286, 96); + _mainList[7] = DrawStruct(12, 235, 117); + _mainList[8] = DrawStruct(14, 260, 117); + _mainList[9] = DrawStruct(16, 286, 117); + _mainList[10] = DrawStruct(20, 235, 148); + _mainList[11] = DrawStruct(22, 260, 148); + _mainList[12] = DrawStruct(24, 286, 148); + _mainList[13] = DrawStruct(26, 235, 169); + _mainList[14] = DrawStruct(28, 260, 169); + _mainList[15] = DrawStruct(30, 286, 169); } void Interface::manageCharacters(bool soundPlayed) { @@ -82,7 +103,7 @@ start: if (!_partyFaces[0]) { // Xeen only uses 24 of possible 30 character slots - loadCharIcons(XEEN_TOTAL_CHARACTERS); + loadCharIcons(); for (int i = 0; i < _vm->_party._partyCount; ++i) _partyFaces[i] = &_charFaces[_vm->_party._partyMembers[i]]; @@ -255,8 +276,8 @@ start: _uiSprites.clear(); } -void Interface::loadCharIcons(int numChars) { - for (int i = 0; i < numChars; ++i) { +void Interface::loadCharIcons() { + for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { // Load new character resource Common::String name = Common::String::format("char%02d.fac", i); _charFaces[i].load(name); @@ -265,6 +286,11 @@ void Interface::loadCharIcons(int numChars) { _dseFace.load("dse.fac"); } +void Interface::loadPartyIcons() { + for (int i = 0; i < _vm->_party._partyCount; ++i) + _partyFaces[i] = &_charFaces[_vm->_party._partyMembers[i]]; +} + void Interface::setupBackground() { _vm->_screen->loadBackground("back.raw"); assembleBorder(); @@ -508,4 +534,54 @@ void Interface::draw3d(bool flag) { warning("TODO"); } +void Interface::animate3d() { + +} + +void Interface::setMonsters() { + +} + +void Interface::setObjects() { + +} + +void Interface::setOutdoorsMonsters() { + +} + +void Interface::setOutdoorsObjects() { + +} + +void Interface::startup() { + Screen &screen = *_vm->_screen; + _iconSprites.load("main.icn"); + + animate3d(); + if (_vm->_map->_isOutdoors) { + setMonsters(); + setObjects(); + } else { + setOutdoorsMonsters(); + setOutdoorsObjects(); + } + draw3d(false); + + _globalSprites.draw(screen._windows[1], 5, Common::Point(232, 9)); + charIconsPrint(false); + + _mainList[0]._sprites = &_globalSprites; + for (int i = 1; i < 16; ++i) + _mainList[i]._sprites = &_iconSprites; +} + +void Interface::mainIconsPrint() { + Screen &screen = *_vm->_screen; + screen._windows[38].close(); + screen._windows[12].close(); + screen._windows[0].drawList(_mainList, 16); + screen._windows[34].update(); +} + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 1ed7afe628..f455957699 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -44,9 +44,11 @@ private: SpriteResource _restoreSprites; SpriteResource _hpSprites; SpriteResource _uiSprites; + SpriteResource _iconSprites; SpriteResource _charFaces[TOTAL_CHARACTERS]; SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; DrawStruct _faceDrawStructs[4]; + DrawStruct _mainList[16]; int _combatCharIds[8]; int _batUIFrame; @@ -64,6 +66,8 @@ private: int _hiliteChar; int _intrIndex1; + void initDrawStructs(); + void assembleBorder(); void setupBackground(); @@ -75,14 +79,30 @@ private: void drawViewBackground(int bgType); void addCharacterToRoster(); + + void animate3d(); + + void setMonsters(); + + void setObjects(); + + void setOutdoorsMonsters(); + + void setOutdoorsObjects(); public: Interface(XeenEngine *vm); void manageCharacters(bool soundPlayed); - void loadCharIcons(int numChars); + void loadCharIcons(); + + void loadPartyIcons(); void draw3d(bool flag); + + void startup(); + + void mainIconsPrint(); }; } // End of namespace Xeen diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 4a3eda6b11..5179b929f2 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -475,7 +475,7 @@ void MonsterData::load(const Common::String &name) { void MonsterData::synchronize(Common::SeekableReadStream &s) { clear(); - MonsterData spr; + MonsterStruct spr; while (!s.eos()) { spr.synchronize(s); push_back(spr); @@ -710,6 +710,7 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { _sideObj = 0; _sideMon = 0; _isOutdoors = false; + _stepped = false; } void Map::load(int mapId) { @@ -722,6 +723,11 @@ void Map::load(int mapId) { PleaseWait::show(_vm); } + _stepped = true; + _vm->_party._mazeId = mapId; + _vm->_events->clearEvents(); + + if (mapId >= 113 && mapId <= 127) { _townPortalSide = 0; } else { @@ -856,7 +862,13 @@ void Map::load(int mapId) { _mobData.synchronize(mobFile, _isOutdoors, _monsterData); mobFile.close(); - // TODO: Loop loading moer data + // TODO: Loop loading moer data / other / cbr? data + + if (_isOutdoors) { + + } else { + + } } } // End of namespace Xeen diff --git a/engines/xeen/map.h b/engines/xeen/map.h index e52e978106..882e495a58 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -258,6 +258,8 @@ private: int _townPortalSide; int _sideObj; int _sideMon; + bool _stepped; +public: bool _isOutdoors; public: Map(XeenEngine *vm); diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 1e164a3166..adf956e9bc 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -50,8 +50,8 @@ struct DrawStruct { int _scale; int _flags; - DrawStruct(SpriteResource *sprites, int frame, int x, int y, int scale = 0, int flags = 0) : - _sprites(sprites), _frame(frame), _x(x), _y(y), _scale(scale), _flags(flags) {} + DrawStruct(int frame, int x, int y, int scale = 0, int flags = 0) : + _sprites(nullptr), _frame(frame), _x(x), _y(y), _scale(scale), _flags(flags) {} DrawStruct(): _sprites(nullptr), _frame(0), _x(0), _y(0), _scale(0), _flags(0) {} }; diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index b3ac7433a3..7321befb08 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -52,6 +52,8 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _face2State = 0; _noDirectionSense = false; _falling = false; + _tillMove = false; + _moveMonsters = false; } XeenEngine::~XeenEngine() { @@ -271,8 +273,7 @@ void XeenEngine::play() { _screen->loadBackground("back.raw"); _screen->loadPalette("mm4.pal"); - _interface->loadCharIcons(_party._partyCount); - _iconsSprites.load("main.icn"); + _interface->loadPartyIcons(); if (getGameID() != GType_WorldOfXeen && !_loadDarkSide) { _loadDarkSide = true; @@ -283,6 +284,28 @@ void XeenEngine::play() { } _map->load(_party._mazeId); + + _interface->startup(); + if (_mode == MODE_0) { + _screen->fadeOut(4); + } + + _screen->_windows[0].update(); + _interface->mainIconsPrint(); + _screen->_windows[0].update(); + _events->setCursor(0); + + _moveMonsters = true; + _tillMove = false; + if (_mode == MODE_0) { + _mode = MODE_1; + _screen->fadeIn(4); + } + + // Main game loop + while (!shouldQuit()) { + _events->pollEventsAndWait(); + } } } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 9938519b9b..776f3196cd 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -93,7 +93,8 @@ private: const XeenGameDescription *_gameDescription; Common::RandomSource _randomSource; int _loadSaveSlot; - SpriteResource _iconsSprites; + bool _moveMonsters; + bool _tillMove; void showIntro(); -- cgit v1.2.3 From eb0c292aafc9b1b819ab1f43d4ec3a059842e96a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 5 Jan 2015 21:17:44 -0500 Subject: XEEN: Start of in-game display implementation --- engines/xeen/files.cpp | 123 +++++++++++++++++++++++---------------------- engines/xeen/files.h | 55 ++++++++++++-------- engines/xeen/interface.cpp | 16 +++--- engines/xeen/interface.h | 4 ++ engines/xeen/map.cpp | 9 ++-- engines/xeen/saves.cpp | 50 ++++++++++++++---- engines/xeen/saves.h | 12 ++++- engines/xeen/xeen.cpp | 2 + 8 files changed, 167 insertions(+), 104 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index a0ca2435a1..b1358d4cdc 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -29,64 +29,10 @@ namespace Xeen { -CCArchive::CCArchive(const Common::String &filename, bool encoded): - _filename(filename), _encoded(encoded) { - File f(filename); - loadIndex(&f); -} - -CCArchive::~CCArchive() { -} - -// Archive implementation -bool CCArchive::hasFile(const Common::String &name) const { - CCEntry ccEntry; - return getHeaderEntry(name, ccEntry); -} - -int CCArchive::listMembers(Common::ArchiveMemberList &list) const { - // CC files don't maintain the original filenames, so we can't list it - return 0; -} - -const Common::ArchiveMemberPtr CCArchive::getMember(const Common::String &name) const { - if (!hasFile(name)) - return Common::ArchiveMemberPtr(); - - return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this)); -} - -Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::String &name) const { - CCEntry ccEntry; - - if (getHeaderEntry(name, ccEntry)) { - // Open the correct CC file - Common::File f; - if (!f.open(_filename)) - error("Could not open CC file"); - - // Read in the data for the specific resource - f.seek(ccEntry._offset); - byte *data = new byte[ccEntry._size]; - f.read(data, ccEntry._size); - - if (_encoded) { - // Decrypt the data - for (int i = 0; i < ccEntry._size; ++i) - data[i] ^= 0x35; - } - - // Return the data as a stream - return new Common::MemoryReadStream(data, ccEntry._size, DisposeAfterUse::YES); - } - - return nullptr; -} - /** - * Hash a given filename to produce the Id that represents it - */ -uint16 CCArchive::convertNameToId(const Common::String &resourceName) const { +* Hash a given filename to produce the Id that represents it +*/ +uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) const { if (resourceName.empty()) return 0xffff; @@ -104,9 +50,9 @@ uint16 CCArchive::convertNameToId(const Common::String &resourceName) const { } /** - * Load the index of a given CC file - */ -void CCArchive::loadIndex(Common::SeekableReadStream *stream) { +* Load the index of a given CC file +*/ +void BaseCCArchive::loadIndex(Common::SeekableReadStream *stream) { int count = stream->readUint16LE(); // Read in the data for the archive's index @@ -136,11 +82,16 @@ void CCArchive::loadIndex(Common::SeekableReadStream *stream) { delete[] rawIndex; } +bool BaseCCArchive::hasFile(const Common::String &name) const { + CCEntry ccEntry; + return getHeaderEntry(name, ccEntry); +} + /** * Given a resource name, returns whether an entry exists, and returns * the header index data for that entry */ -bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const { +bool BaseCCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const { uint16 id = convertNameToId(resourceName); // Loop through the index @@ -155,6 +106,56 @@ bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEn return false; } +const Common::ArchiveMemberPtr BaseCCArchive::getMember(const Common::String &name) const { + if (!hasFile(name)) + return Common::ArchiveMemberPtr(); + + return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this)); +} + +int BaseCCArchive::listMembers(Common::ArchiveMemberList &list) const { + // CC files don't maintain the original filenames, so we can't list it + return 0; +} + +/*------------------------------------------------------------------------*/ + +CCArchive::CCArchive(const Common::String &filename, bool encoded): + _filename(filename), _encoded(encoded) { + File f(filename); + loadIndex(&f); +} + +CCArchive::~CCArchive() { +} + +Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::String &name) const { + CCEntry ccEntry; + + if (getHeaderEntry(name, ccEntry)) { + // Open the correct CC file + Common::File f; + if (!f.open(_filename)) + error("Could not open CC file"); + + // Read in the data for the specific resource + f.seek(ccEntry._offset); + byte *data = new byte[ccEntry._size]; + f.read(data, ccEntry._size); + + if (_encoded) { + // Decrypt the data + for (int i = 0; i < ccEntry._size; ++i) + data[i] ^= 0x35; + } + + // Return the data as a stream + return new Common::MemoryReadStream(data, ccEntry._size, DisposeAfterUse::YES); + } + + return nullptr; +} + /*------------------------------------------------------------------------*/ /** diff --git a/engines/xeen/files.h b/engines/xeen/files.h index 3e38ad842c..6e560ca334 100644 --- a/engines/xeen/files.h +++ b/engines/xeen/files.h @@ -58,41 +58,52 @@ public: }; /** -* Xeen CC file implementation +* Details of a single entry in a CC file index */ -class CCArchive : public Common::Archive { -private: - /** - * Details of a single entry in a CC file index - */ - struct CCEntry { - uint16 _id; - uint32 _offset; - uint16 _size; - - CCEntry() : _id(0), _offset(0), _size(0) {} - CCEntry(uint16 id, uint32 offset, uint32 size) - : _id(id), _offset(offset), _size(size) { - } - }; - - Common::Array<CCEntry> _index; - Common::String _filename; - bool _encoded; +struct CCEntry { + uint16 _id; + uint32 _offset; + uint16 _size; + + CCEntry() : _id(0), _offset(0), _size(0) {} + CCEntry(uint16 id, uint32 offset, uint32 size) + : _id(id), _offset(offset), _size(size) { + } +}; +/** +* Base Xeen CC file implementation +*/ +class BaseCCArchive : public Common::Archive { +private: uint16 convertNameToId(const Common::String &resourceName) const; +protected: + Common::Array<CCEntry> _index; void loadIndex(Common::SeekableReadStream *stream); bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const; public: - CCArchive(const Common::String &filename, bool encoded = true); - virtual ~CCArchive(); + BaseCCArchive() {} // Archive implementation virtual bool hasFile(const Common::String &name) const; virtual int listMembers(Common::ArchiveMemberList &list) const; virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const; +}; + +/** +* Xeen CC file implementation +*/ +class CCArchive : public BaseCCArchive { +private: + Common::String _filename; + bool _encoded; +public: + CCArchive(const Common::String &filename, bool encoded = true); + virtual ~CCArchive(); + + // Archive implementation virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; }; diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 4f40c4730d..daeb4402e5 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -71,10 +71,7 @@ void Interface::initDrawStructs() { _mainList[15] = DrawStruct(30, 286, 169); } -void Interface::manageCharacters(bool soundPlayed) { - Screen &screen = *_vm->_screen; - EventsManager &events = *_vm->_events; - bool flag = false; +void Interface::setup() { _globalSprites.load("global.icn"); _borderSprites.load("border.icn"); _spellFxSprites.load("spellfx.icn"); @@ -84,7 +81,6 @@ void Interface::manageCharacters(bool soundPlayed) { _hpSprites.load("hpbars.icn"); _uiSprites.load("inn.icn"); -start: // Get mappings to the active characters in the party _vm->_party._activeParty.resize(_vm->_party._partyCount); for (int i = 0; i < _vm->_party._partyCount; ++i) { @@ -92,7 +88,14 @@ start: } _isEarlyGame = _vm->_party._minutes >= 300; +} +void Interface::manageCharacters(bool soundPlayed) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + bool flag = false; + +start: if (_vm->_party._mazeId != 0) { _vm->_mode = MODE_0; _buttonsLoaded = true; @@ -279,7 +282,7 @@ start: void Interface::loadCharIcons() { for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { // Load new character resource - Common::String name = Common::String::format("char%02d.fac", i); + Common::String name = Common::String::format("char%02d.fac", i + 1); _charFaces[i].load(name); } @@ -556,6 +559,7 @@ void Interface::setOutdoorsObjects() { void Interface::startup() { Screen &screen = *_vm->_screen; + loadCharIcons(); _iconSprites.load("main.icn"); animate3d(); diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index f455957699..b19f031ac4 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -66,6 +66,8 @@ private: int _hiliteChar; int _intrIndex1; + void loadSprites(); + void initDrawStructs(); void assembleBorder(); @@ -92,6 +94,8 @@ private: public: Interface(XeenEngine *vm); + void setup(); + void manageCharacters(bool soundPlayed); void loadCharIcons(); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 5179b929f2..5e98c519f4 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -669,6 +669,7 @@ void MonsterObjectData::synchronize(Common::SeekableReadStream &s, } // merge up monsters + _monsters.resize(monData.size()); for (uint i = 0; i < monData.size(); ++i) { MazeMonster &dest = _monsters[i]; dest._position = monData[i]._pos; @@ -808,7 +809,7 @@ void Map::load(int mapId) { if (!textLoaded) { textLoaded = true; Common::String txtName = Common::String::format("%s%c%03u.txt", - isDarkCc ? "dark" : "xeen", mapId >= 100 ? 'x' : '0'); + isDarkCc ? "dark" : "xeen", mapId >= 100 ? 'x' : '0', mapId); File fText(txtName); char mazeName[33]; fText.read(mazeName, 33); @@ -819,13 +820,13 @@ void Map::load(int mapId) { // Load the monster data Common::String mobName = Common::String::format("maze%c%03u.mob", - (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); + (mapId >= 100) ? 'x' : '0', mapId); File mobFile(mobName); _mobData.synchronize(mobFile, _isOutdoors, _monsterData); mobFile.close(); Common::String headName = Common::String::format("aaze%c%03u.hed", - (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); + (mapId >= 100) ? 'x' : '0', mapId); File headFile(headName); _headData.synchronize(headFile); headFile.close(); @@ -846,7 +847,7 @@ void Map::load(int mapId) { // Move to next surrounding maze MazeData *baseMaze = &_mazeData[MAP_GRID_PRIOR_INDEX[idx]]; mapId = baseMaze->_surroundingMazes[MAP_GRID_PRIOR_DIRECTION[idx]]; - if (mapId) { + if (!mapId) { baseMaze = &_mazeData[MAP_GRID_PRIOR_INDEX2[idx]]; mapId = baseMaze->_surroundingMazes[MAP_GRID_PRIOR_DIRECTION2[idx]]; } diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index 95957c4daa..ae29dd1149 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -22,6 +22,7 @@ #include "common/scummsys.h" #include "common/algorithm.h" +#include "common/memstream.h" #include "xeen/saves.h" #include "xeen/files.h" #include "xeen/xeen.h" @@ -29,7 +30,13 @@ namespace Xeen { SavesManager::SavesManager(XeenEngine *vm, Party &party, Roster &roster) : - _vm(vm), _party(party), _roster(roster) { + BaseCCArchive(), _vm(vm), _party(party), _roster(roster) { + SearchMan.add("saves", this, 0, false); + _data = nullptr; +} + +SavesManager::~SavesManager() { + delete[] _data; } /** @@ -57,24 +64,47 @@ void SavesManager::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP) } } -/** - * Sets up the dynamic data for the game for a new game - */ -void SavesManager::reset() { - Common::String name(_vm->getGameID() == GType_Clouds ? "xeen.cur" : "dark.cur"); - CCArchive cur(name, false); - - Common::SeekableReadStream *chr = cur.createReadStreamForMember("maze.chr"); +Common::SeekableReadStream *SavesManager::createReadStreamForMember(const Common::String &name) const { + CCEntry ccEntry; + + if (getHeaderEntry(name, ccEntry)) { + // Open the correct CC entry + return new Common::MemoryReadStream(_data + ccEntry._offset, ccEntry._size); + } + + return nullptr; +} + +void SavesManager::load(Common::SeekableReadStream *stream) { + loadIndex(stream); + + delete[] _data; + _data = new byte[stream->size()]; + stream->seek(0); + stream->read(_data, stream->size()); + + // Load in the character stats and active party + Common::SeekableReadStream *chr = createReadStreamForMember("maze.chr"); Common::Serializer sChr(chr, nullptr); _roster.synchronize(sChr); delete chr; - Common::SeekableReadStream *pty = cur.createReadStreamForMember("maze.pty"); + Common::SeekableReadStream *pty = createReadStreamForMember("maze.pty"); Common::Serializer sPty(pty, nullptr); _party.synchronize(sPty); delete pty; } +/** + * Sets up the dynamic data for the game for a new game + */ +void SavesManager::reset() { + Common::String name(_vm->getGameID() == GType_Clouds ? "xeen.cur" : "dark.cur"); + File f(name); + + load(&f); +} + void SavesManager::readCharFile() { warning("TODO: readCharFile"); } diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h index 1e67638fe4..ed4b80b29d 100644 --- a/engines/xeen/saves.h +++ b/engines/xeen/saves.h @@ -27,6 +27,7 @@ #include "common/savefile.h" #include "graphics/surface.h" #include "xeen/party.h" +#include "xeen/files.h" namespace Xeen { @@ -39,20 +40,29 @@ struct XeenSavegameHeader { int _totalFrames; }; -class SavesManager { +class SavesManager: public BaseCCArchive { private: XeenEngine *_vm; Party &_party; Roster &_roster; + byte *_data; + + void load(Common::SeekableReadStream *stream); public: static void syncBitFlags(Common::Serializer &s, bool *startP, bool *endP); public: SavesManager(XeenEngine *vm, Party &party, Roster &roster); + + ~SavesManager(); + void reset(); void readCharFile(); void writeCharFile(); + + // Archive implementation + virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; }; } // End of namespace Xeen diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 7321befb08..948b4154fe 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -54,6 +54,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _falling = false; _tillMove = false; _moveMonsters = false; + _mode = MODE_0; } XeenEngine::~XeenEngine() { @@ -271,6 +272,7 @@ void XeenEngine::playGame() { void XeenEngine::play() { // TODO: Init variables + _interface->setup(); _screen->loadBackground("back.raw"); _screen->loadPalette("mm4.pal"); _interface->loadPartyIcons(); -- cgit v1.2.3 From 31f4f5b843400531d3e091ae0eb673d6dacc227d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 6 Jan 2015 19:09:07 -0500 Subject: XEEN: More interface setup and UI button definitions --- engines/xeen/dialogs.cpp | 2 +- engines/xeen/dialogs.h | 2 +- engines/xeen/interface.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/interface.h | 9 +++++++++ engines/xeen/xeen.cpp | 4 ++-- engines/xeen/xeen.h | 3 +-- 6 files changed, 63 insertions(+), 6 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index 8e8e7521cb..c677fc8efb 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -46,7 +46,7 @@ void ButtonContainer::restoreButtons() { _buttons = _savedButtons.pop(); } -void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw = true) { +void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw) { _buttons.push_back(UIButton(bounds, val, sprites, draw)); } diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h index 987df6b2f1..229c40a2da 100644 --- a/engines/xeen/dialogs.h +++ b/engines/xeen/dialogs.h @@ -66,7 +66,7 @@ public: void restoreButtons(); - void addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw); + void addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw = true); }; class SettingsBaseDialog : public ButtonContainer { diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index daeb4402e5..c27cdb9bd3 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -38,11 +38,16 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { _powerShieldUIFrame = 0; _holyBonusUIFrame = 0; _heroismUIFrame = 0; + _flipUIFrame = 0; _isEarlyGame = false; _buttonsLoaded = false; _hiliteChar = -1; Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); _intrIndex1 = 0; + _flipWtr = false; + _flag1 = false; + _flag2 = false; + _tillMove = 0; initDrawStructs(); } @@ -534,6 +539,17 @@ void Interface::draw3d(bool flag) { if (!screen._windows[11]._enabled) return; + _flipUIFrame = (_flipUIFrame + 1) % 4; + if (_flipUIFrame == 0) + _flipWtr = !_flipWtr; + if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_2) && + !_flag1 && _vm->_moveMonsters) { + if (--_tillMove == 0) + moveMonsters(); + } + + // TODO: more + warning("TODO"); } @@ -578,6 +594,10 @@ void Interface::startup() { _mainList[0]._sprites = &_globalSprites; for (int i = 1; i < 16; ++i) _mainList[i]._sprites = &_iconSprites; + + setIconButtons(); + + _tillMove = false; } void Interface::mainIconsPrint() { @@ -588,4 +608,33 @@ void Interface::mainIconsPrint() { screen._windows[34].update(); } +void Interface::moveMonsters() { + +} + +void Interface::setIconButtons() { + clearButtons(); + + addButton(Common::Rect(235, 75, 259, 95), 83, &_iconSprites); + addButton(Common::Rect(260, 75, 284, 95), 67, &_iconSprites); + addButton(Common::Rect(286, 75, 310, 95), 82, &_iconSprites); + addButton(Common::Rect(235, 96, 259, 116), 66, &_iconSprites); + addButton(Common::Rect(260, 96, 284, 116), 68, &_iconSprites); + addButton(Common::Rect(286, 96, 310, 116), 86, &_iconSprites); + addButton(Common::Rect(235, 117, 259, 137), 77, &_iconSprites); + addButton(Common::Rect(260, 117, 284, 137), 73, &_iconSprites); + addButton(Common::Rect(286, 117, 310, 137), 81, &_iconSprites); + addButton(Common::Rect(109, 137, 122, 147), 9, &_iconSprites); + addButton(Common::Rect(235, 148, 259, 168), 240, &_iconSprites); + addButton(Common::Rect(260, 148, 284, 168), 242, &_iconSprites); + addButton(Common::Rect(286, 148, 310, 168), 241, &_iconSprites); + addButton(Common::Rect(235, 169, 259, 189), 176, &_iconSprites); + addButton(Common::Rect(260, 169, 284, 189), 243, &_iconSprites); + addButton(Common::Rect(286, 169, 310, 189), 177, &_iconSprites); + addButton(Common::Rect(236, 11, 308, 69), 61, &_iconSprites, false); + addButton(Common::Rect(239, 27, 312, 37), 49, &_iconSprites, false); + addButton(Common::Rect(239, 37, 312, 47), 50, &_iconSprites, false); + addButton(Common::Rect(239, 47, 312, 57), 51, &_iconSprites, false); +} + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index b19f031ac4..475e71bbce 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -60,11 +60,16 @@ private: int _powerShieldUIFrame; int _holyBonusUIFrame; int _heroismUIFrame; + int _flipUIFrame; bool _isEarlyGame; bool _buttonsLoaded; Common::String _interfaceText; int _hiliteChar; int _intrIndex1; + bool _flipWtr; + bool _flag1; + bool _flag2; + byte _tillMove; void loadSprites(); @@ -91,6 +96,10 @@ private: void setOutdoorsMonsters(); void setOutdoorsObjects(); + + void moveMonsters(); + + void setIconButtons(); public: Interface(XeenEngine *vm); diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 948b4154fe..c2abdd9e9f 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -52,7 +52,6 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _face2State = 0; _noDirectionSense = false; _falling = false; - _tillMove = false; _moveMonsters = false; _mode = MODE_0; } @@ -298,12 +297,13 @@ void XeenEngine::play() { _events->setCursor(0); _moveMonsters = true; - _tillMove = false; if (_mode == MODE_0) { _mode = MODE_1; _screen->fadeIn(4); } + _moveMonsters = true; + // Main game loop while (!shouldQuit()) { _events->pollEventsAndWait(); diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 776f3196cd..44deaee43c 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -93,8 +93,6 @@ private: const XeenGameDescription *_gameDescription; Common::RandomSource _randomSource; int _loadSaveSlot; - bool _moveMonsters; - bool _tillMove; void showIntro(); @@ -146,6 +144,7 @@ public: int _face2State; bool _noDirectionSense; bool _falling; + bool _moveMonsters; public: XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); virtual ~XeenEngine(); -- cgit v1.2.3 From fa0d7722f1c7826887b6f2b28d2d6829c77c717a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 6 Jan 2015 22:48:04 -0500 Subject: XEEN: Work on loading sprites for monsters and objects in Map::load --- engines/xeen/map.cpp | 70 +++++++++++++++++++++++++++++++++++++++++------- engines/xeen/map.h | 7 +++++ engines/xeen/sprites.cpp | 20 +++++++++++++- engines/xeen/sprites.h | 6 ++++- 4 files changed, 91 insertions(+), 12 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 5e98c519f4..f7620b1852 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -619,6 +619,16 @@ bool MobStruct::synchronize(Common::SeekableReadStream &s) { /*------------------------------------------------------------------------*/ +MazeObject::MazeObject() { + _number = 0; + _frame = 0; + _id = 0; + _direction = DIR_NORTH; + _flipped = false; +} + +/*------------------------------------------------------------------------*/ + MonsterObjectData::MonsterObjectData(XeenEngine *vm): _vm(vm) { } @@ -855,20 +865,60 @@ void Map::load(int mapId) { // TODO: Switch setting flags that don't seem to ever be used - // Reload object data, since prior loop iterations replaced the data - // for the main map with all the surrounding mazes - Common::String mobName = Common::String::format("maze%c%03u.mob", - (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); - File mobFile(mobName); - _mobData.synchronize(mobFile, _isOutdoors, _monsterData); - mobFile.close(); - // TODO: Loop loading moer data / other / cbr? data + // Load secondary bj file for the objects + Common::String filename; + for (uint i = 0; i < _mobData._objects.size(); ++i) { + if (_vm->_party._cloudsEnd && _mobData._objects[i]._id == 85 && + _vm->_party._mazeId == 27 && isDarkCc) { + // TODO: Flags set that don't seem to be used + } else if (_vm->_party._mazeId == 12 && _vm->_party._gameFlags[43] && + _mobData._objects[i]._id == 118 && !isDarkCc) { + filename = "085.obj"; + _mobData._objects[0]._id = 85; + } else { + filename = Common::String::format("%03u.%cbj", _mobData._objects[i]._id, + _mobData._objects[i]._id >= 100 ? 'o' : '0'); + } - if (_isOutdoors) { + // Read in the secondary object data + File f(filename); + Common::Array<byte> &b = _mobData._objects[i]._objBj; + b.resize(f.size()); + f.read(&b[0], f.size()); + } - } else { + // Load sprite resources for monster standard and attack animations + int monsterNum = 1; + int monsterImgNums[95]; + Common::fill(&monsterImgNums[0], &monsterImgNums[95], 0); + for (uint i = 0; i < _mobData._monsters.size(); ++i, ++monsterNum) { + MonsterStruct &monsterStruct = _monsterData[i]; + int monsterImgNum = monsterStruct._imageNumber; + filename = Common::String::format("%03u.mon", monsterImgNum); + + if (!monsterImgNums[monsterImgNum]) { + _mobData._monsters[i]._sprites.load(filename); + } else { + _mobData._monsters[i]._sprites = _mobData._monsters[ + monsterImgNums[monsterImgNum] - 1]._sprites; + } + + filename = Common::String::format("%03u.att", monsterImgNum); + if (!monsterImgNums[monsterImgNum]) { + _mobData._monsters[i]._attackSprites.load(filename); + monsterImgNums[monsterImgNum] = monsterNum; + } else { + _mobData._monsters[i]._attackSprites = _mobData._monsters[ + monsterImgNums[monsterImgNum] - 1]._attackSprites;; + } + } + // Load wall picture sprite resources + for (uint i = 0; i < _mobData._wallImages.size(); ++i) { + filename = Common::String::format("%03u.pic", _mobData._wallImages[i]._id); + // TODO: Form WallImages struct like _monsters and _objects has + //_mobData._wallImages[i]._sprites.load(filename); } } diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 882e495a58..c4ab348c91 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -24,6 +24,7 @@ #define XEEN_MAP_H #include "common/stream.h" +#include "common/array.h" #include "common/rect.h" #include "xeen/party.h" #include "xeen/sprites.h" @@ -199,12 +200,16 @@ public: }; struct MazeObject { +public: Common::Point _position; int _number; int _frame; int _id; Direction _direction; bool _flipped; + Common::Array<byte> _objBj; +public: + MazeObject(); }; struct MazeMonster { @@ -215,6 +220,8 @@ struct MazeMonster { int _hp; int _effect1, _effect2; int _effect3; + SpriteResource _sprites; + SpriteResource _attackSprites; }; class MonsterObjectData { diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 598870dc57..74f2b1d04a 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -43,6 +43,21 @@ SpriteResource::~SpriteResource() { clear(); } +SpriteResource &SpriteResource::operator=(const SpriteResource &src) { + delete[] _data; + _index.clear(); + + _filesize = src._filesize; + _data = new byte[_filesize]; + Common::copy(src._data, src._data + _filesize, _data); + + _index.resize(src._index.size()); + for (uint i = 0; i < src._index.size(); ++i) + _index[i] = src._index[i]; + + return *this; +} + void SpriteResource::load(const Common::String &filename) { // Open the resource File f(filename); @@ -173,7 +188,10 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi destPos.x + xOffset + width, destPos.y + yOffset + height)); } -void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const { +void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, int flags) const { + // TODO: Support the different flags + assert(!flags); + drawOffset(dest, _index[frame]._offset1, destPos); if (_index[frame]._offset2) drawOffset(dest, _index[frame]._offset2, destPos); diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index 998d5d3e79..7f937abe8c 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -33,6 +33,8 @@ namespace Xeen { class XeenEngine; +enum SpriteFlags { SPRFLAG_HORIZ_FLIPPED = 0x8000 }; + class SpriteResource { private: struct IndexEntry { @@ -49,11 +51,13 @@ public: virtual ~SpriteResource(); + SpriteResource &operator=(const SpriteResource &src); + void load(const Common::String &filename); void clear(); - void draw(XSurface &dest, int frame, const Common::Point &destPos) const; + void draw(XSurface &dest, int frame, const Common::Point &destPos, int flags = 0) const; void draw(XSurface &dest, int frame) const; -- cgit v1.2.3 From be53adbefc09f58325015b52b88f9290509a39f1 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 7 Jan 2015 08:47:24 -0500 Subject: XEEN: Implemented map loading of wall item sprites --- engines/xeen/map.cpp | 44 ++++++++++++++++++++++++++++++++++++-------- engines/xeen/map.h | 18 +++++++++++++++--- 2 files changed, 51 insertions(+), 11 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index f7620b1852..fae9efe4d6 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -629,6 +629,24 @@ MazeObject::MazeObject() { /*------------------------------------------------------------------------*/ +MazeMonster::MazeMonster() { + _frame = 0; + _id = 0; + _refId = 0; + _hp = 0; + _effect1 = _effect2 = 0; + _effect3 = 0; +} + +/*------------------------------------------------------------------------*/ + +MazeWallItem::MazeWallItem() { + _id = 0; + _direction = DIR_NORTH; +} + +/*------------------------------------------------------------------------*/ + MonsterObjectData::MonsterObjectData(XeenEngine *vm): _vm(vm) { } @@ -636,12 +654,13 @@ void MonsterObjectData::synchronize(Common::SeekableReadStream &s, bool isOutdoors, MonsterData monsterData) { _objects.clear(); _monsters.clear(); - _wallPicIds.clear(); - _wallImages.clear(); + _wallItems.clear(); Common::Array<int> objectSprites; Common::Array<int> monsterIds; + Common::Array<int> wallPicIds; Common::Array<MobStruct> objData; Common::Array<MobStruct> monData; + Common::Array<MobStruct> wallItemData; byte b; for (int i = 0; i < 16; ++i) { @@ -654,7 +673,7 @@ void MonsterObjectData::synchronize(Common::SeekableReadStream &s, } for (int i = 0; i < 16; ++i) { if ((b = s.readByte()) != 0xff) - _wallPicIds.push_back(b); + wallPicIds.push_back(b); } MobStruct mobStruct; @@ -664,7 +683,7 @@ void MonsterObjectData::synchronize(Common::SeekableReadStream &s, monData.push_back(mobStruct); if (!isOutdoors) { while (mobStruct.synchronize(s)) - _wallImages.push_back(mobStruct); + wallItemData.push_back(mobStruct); } // Merge up objects @@ -693,6 +712,16 @@ void MonsterObjectData::synchronize(Common::SeekableReadStream &s, if (mon._animationEffect) dest._effect3 = _vm->getRandomNumber(7); } + + // Merge up wall items + _wallItems.clear(); + for (uint i = 0; i < wallItemData.size(); ++i) { + MazeWallItem &dest = _wallItems[i]; + dest._position = wallItemData[i]._pos; + dest._id = wallItemData[i]._id; + dest._refId = wallPicIds[dest._id]; + dest._direction = wallItemData[i]._direction; + } } /*------------------------------------------------------------------------*/ @@ -915,10 +944,9 @@ void Map::load(int mapId) { } // Load wall picture sprite resources - for (uint i = 0; i < _mobData._wallImages.size(); ++i) { - filename = Common::String::format("%03u.pic", _mobData._wallImages[i]._id); - // TODO: Form WallImages struct like _monsters and _objects has - //_mobData._wallImages[i]._sprites.load(filename); + for (uint i = 0; i < _mobData._wallItems.size(); ++i) { + filename = Common::String::format("%03u.pic", _mobData._wallItems[i]._refId); + _mobData._wallItems[i]._sprites.load(filename); } } diff --git a/engines/xeen/map.h b/engines/xeen/map.h index c4ab348c91..f39f2d8622 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -208,7 +208,7 @@ public: Direction _direction; bool _flipped; Common::Array<byte> _objBj; -public: + MazeObject(); }; @@ -222,6 +222,19 @@ struct MazeMonster { int _effect3; SpriteResource _sprites; SpriteResource _attackSprites; + + MazeMonster(); +}; + +class MazeWallItem { +public: + Common::Point _position; + int _id; + int _refId; + Direction _direction; + SpriteResource _sprites; +public: + MazeWallItem(); }; class MonsterObjectData { @@ -230,8 +243,7 @@ private: public: Common::Array<MazeObject> _objects; Common::Array<MazeMonster> _monsters; - Common::Array<int> _wallPicIds; - Common::Array<MobStruct> _wallImages; + Common::Array<MazeWallItem> _wallItems; public: MonsterObjectData(XeenEngine *vm); -- cgit v1.2.3 From cd7c00ca8c93258d7b6c3ef92fc32452df1052cb Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 7 Jan 2015 19:40:13 -0500 Subject: XEEN: Minor standardisation on monster/object Ids --- engines/xeen/map.cpp | 34 ++++++++++++++++++---------------- engines/xeen/map.h | 6 +++--- 2 files changed, 21 insertions(+), 19 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index fae9efe4d6..15c696bf94 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -620,9 +620,9 @@ bool MobStruct::synchronize(Common::SeekableReadStream &s) { /*------------------------------------------------------------------------*/ MazeObject::MazeObject() { - _number = 0; - _frame = 0; _id = 0; + _frame = 0; + _refId = 0; _direction = DIR_NORTH; _flipped = false; } @@ -691,8 +691,8 @@ void MonsterObjectData::synchronize(Common::SeekableReadStream &s, for (uint i = 0; i < objData.size(); ++i) { MazeObject &dest = _objects[i]; dest._position = objData[i]._pos; - dest._number = objData[i]._id; - dest._id = objectSprites[dest._number]; + dest._id = objData[i]._id; + dest._refId = objectSprites[dest._id]; dest._direction = objData[i]._direction; dest._frame = 100; } @@ -857,7 +857,7 @@ void Map::load(int mapId) { _mazeName = Common::String(mazeName); fText.close(); - // Load the monster data + // Load the monster/object data Common::String mobName = Common::String::format("maze%c%03u.mob", (mapId >= 100) ? 'x' : '0', mapId); File mobFile(mobName); @@ -894,27 +894,29 @@ void Map::load(int mapId) { // TODO: Switch setting flags that don't seem to ever be used + // Reload the monster data for the main maze that we're loading + Common::String filename = Common::String::format("maze%c%03u.mob", + (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); + File mobFile(filename); + _mobData.synchronize(mobFile, _isOutdoors, _monsterData); + mobFile.close(); - // Load secondary bj file for the objects - Common::String filename; + // Load sprites for the objects for (uint i = 0; i < _mobData._objects.size(); ++i) { - if (_vm->_party._cloudsEnd && _mobData._objects[i]._id == 85 && + if (_vm->_party._cloudsEnd && _mobData._objects[i]._refId == 85 && _vm->_party._mazeId == 27 && isDarkCc) { // TODO: Flags set that don't seem to be used } else if (_vm->_party._mazeId == 12 && _vm->_party._gameFlags[43] && - _mobData._objects[i]._id == 118 && !isDarkCc) { + _mobData._objects[i]._refId == 118 && !isDarkCc) { filename = "085.obj"; _mobData._objects[0]._id = 85; } else { - filename = Common::String::format("%03u.%cbj", _mobData._objects[i]._id, - _mobData._objects[i]._id >= 100 ? 'o' : '0'); + filename = Common::String::format("%03d.%cbj", _mobData._objects[i]._refId, + _mobData._objects[i]._refId >= 100 ? 'o' : '0'); } - // Read in the secondary object data - File f(filename); - Common::Array<byte> &b = _mobData._objects[i]._objBj; - b.resize(f.size()); - f.read(&b[0], f.size()); + // Read in the object sprites + _mobData._objects[i]._sprites.load(filename); } // Load sprite resources for monster standard and attack animations diff --git a/engines/xeen/map.h b/engines/xeen/map.h index f39f2d8622..7c0344b9a4 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -202,12 +202,12 @@ public: struct MazeObject { public: Common::Point _position; - int _number; - int _frame; int _id; + int _frame; + int _refId; Direction _direction; bool _flipped; - Common::Array<byte> _objBj; + SpriteResource _sprites; MazeObject(); }; -- cgit v1.2.3 From 96d086ab9cc28a2145072487b60036f916b28774 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 7 Jan 2015 22:11:18 -0500 Subject: XEEN: Add prefix support to CC files, initial save state fixes --- engines/xeen/files.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++++---- engines/xeen/files.h | 12 ++++++++++-- engines/xeen/map.cpp | 4 ++-- engines/xeen/saves.cpp | 33 +++++++++++++++++++++++++++++++-- 4 files changed, 87 insertions(+), 10 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index b1358d4cdc..79387f2e24 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -39,6 +39,14 @@ uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) const Common::String name = resourceName; name.toUppercase(); + // Check if a resource number is being directly specified + if (name.size() == 4) { + char *endPtr; + uint16 num = (uint16)strtol(name.c_str(), &endPtr, 16); + if (!*endPtr) + return num; + } + const byte *msgP = (const byte *)name.c_str(); int total = *msgP++; for (; *msgP; total += *msgP++) { @@ -121,7 +129,15 @@ int BaseCCArchive::listMembers(Common::ArchiveMemberList &list) const { /*------------------------------------------------------------------------*/ CCArchive::CCArchive(const Common::String &filename, bool encoded): - _filename(filename), _encoded(encoded) { + BaseCCArchive(), _filename(filename), _encoded(encoded) { + File f(filename); + loadIndex(&f); +} + +CCArchive::CCArchive(const Common::String &filename, const Common::String &prefix, + bool encoded): BaseCCArchive(), _filename(filename), + _prefix(prefix), _encoded(encoded) { + _prefix.toLowercase(); File f(filename); loadIndex(&f); } @@ -129,6 +145,25 @@ CCArchive::CCArchive(const Common::String &filename, bool encoded): CCArchive::~CCArchive() { } +bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const { + Common::String resName = resourceName; + + if (!_prefix.empty() && resName.contains('|')) { + resName.toLowercase(); + Common::String prefix = _prefix + "|"; + + if (!strncmp(resName.c_str(), prefix.c_str(), prefix.size())) + // Matching CC prefix, so strip it off and allow processing to + // continue onto the base getHeaderEntry method + resName = Common::String(resName.c_str() + prefix.size()); + else + // Not matching prefix, so don't allow a match + return false; + } + + return BaseCCArchive::getHeaderEntry(resName, ccEntry); +} + Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::String &name) const { CCEntry ccEntry; @@ -166,9 +201,9 @@ FileManager::FileManager(XeenEngine *vm) { _isDarkCc = vm->getGameID() != GType_Clouds; if (_isDarkCc) - SearchMan.add("dark", new CCArchive("dark.cc")); - SearchMan.add("xeen", new CCArchive("xeen.cc")); - SearchMan.add("intro", new CCArchive("intro.cc")); + SearchMan.add("dark", new CCArchive("dark.cc", "dark", true)); + SearchMan.add("xeen", new CCArchive("xeen.cc", "xeen", true)); + SearchMan.add("intro", new CCArchive("intro.cc", "intro", true)); } /*------------------------------------------------------------------------*/ @@ -181,4 +216,9 @@ void File::openFile(const Common::String &filename) { error("Could not open file - %s", filename.c_str()); } +void File::openFile(const Common::String &filename, Common::Archive &archive) { + if (!Common::File::open(filename, archive)) + error("Could not open file - %s", filename.c_str()); +} + } // End of namespace Xeen diff --git a/engines/xeen/files.h b/engines/xeen/files.h index 6e560ca334..343aea1e74 100644 --- a/engines/xeen/files.h +++ b/engines/xeen/files.h @@ -52,9 +52,13 @@ class File : public Common::File { public: File() : Common::File() {} File(const Common::String &filename) { openFile(filename); } + File(const Common::String &filename, Common::Archive &archive) { + openFile(filename, archive); + } virtual ~File() {} void openFile(const Common::String &filename); + void openFile(const Common::String &filename, Common::Archive &archive); }; /** @@ -82,7 +86,7 @@ protected: void loadIndex(Common::SeekableReadStream *stream); - bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const; + virtual bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const; public: BaseCCArchive() {} @@ -98,9 +102,13 @@ public: class CCArchive : public BaseCCArchive { private: Common::String _filename; + Common::String _prefix; bool _encoded; +protected: + virtual bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const; public: - CCArchive(const Common::String &filename, bool encoded = true); + CCArchive(const Common::String &filename, bool encoded); + CCArchive(const Common::String &filename, const Common::String &prefix, bool encoded); virtual ~CCArchive(); // Archive implementation diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 15c696bf94..a3a4063ee9 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -714,7 +714,7 @@ void MonsterObjectData::synchronize(Common::SeekableReadStream &s, } // Merge up wall items - _wallItems.clear(); + _wallItems.resize(1); for (uint i = 0; i < wallItemData.size(); ++i) { MazeWallItem &dest = _wallItems[i]; dest._position = wallItemData[i]._pos; @@ -897,7 +897,7 @@ void Map::load(int mapId) { // Reload the monster data for the main maze that we're loading Common::String filename = Common::String::format("maze%c%03u.mob", (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); - File mobFile(filename); + File mobFile(filename, *_vm->_saves); _mobData.synchronize(mobFile, _isOutdoors, _monsterData); mobFile.close(); diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index ae29dd1149..36bb7bda1a 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -99,10 +99,39 @@ void SavesManager::load(Common::SeekableReadStream *stream) { * Sets up the dynamic data for the game for a new game */ void SavesManager::reset() { - Common::String name(_vm->getGameID() == GType_Clouds ? "xeen.cur" : "dark.cur"); - File f(name); + Common::String prefix = _vm->getGameID() == GType_Clouds ? "xeen|" : "dark|"; + Common::MemoryWriteStreamDynamic saveFile(DisposeAfterUse::YES); + Common::File fIn; + + for (int i = 0; i <= 5; ++i) { + Common::String filename = prefix + Common::String::format("2A%dC", i); + if (fIn.exists(filename)) { + // Read in the next resource + fIn.open(filename); + byte *data = new byte[fIn.size()]; + fIn.read(data, fIn.size()); + + // Copy it to the combined savefile resource + saveFile.write(data, fIn.size()); + delete[] data; + fIn.close(); + } + } + Common::MemoryReadStream f(saveFile.getData(), saveFile.size()); load(&f); + + // Set up the party and characters from dark.cur + CCArchive gameCur("xeen.cur", false); + File fParty("maze.pty", gameCur); + Common::Serializer sParty(&fParty, nullptr); + _party.synchronize(sParty); + fParty.close(); + + File fChar("maze.chr", gameCur); + Common::Serializer sChar(&fChar, nullptr); + _roster.synchronize(sChar); + fChar.close(); } void SavesManager::readCharFile() { -- cgit v1.2.3 From f9414fe5259547b6499d9fb8ccb54bdc0bebb0ed Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 7 Jan 2015 22:51:03 -0500 Subject: XEEN: Further fix for savegame initialization --- engines/xeen/map.cpp | 16 ++++++++-------- engines/xeen/saves.cpp | 5 +++-- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index a3a4063ee9..63d5542d84 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -829,7 +829,7 @@ void Map::load(int mapId) { if (mapId != 0) { // Load in the maze's data file - Common::String datName = Common::String::format("maze%c%03u.dat", + Common::String datName = Common::String::format("maze%c%03d.dat", (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); File datFile(datName); mazeData->synchronize(datFile); @@ -847,7 +847,7 @@ void Map::load(int mapId) { // Handle loading text data if (!textLoaded) { textLoaded = true; - Common::String txtName = Common::String::format("%s%c%03u.txt", + Common::String txtName = Common::String::format("%s%c%03d.txt", isDarkCc ? "dark" : "xeen", mapId >= 100 ? 'x' : '0', mapId); File fText(txtName); char mazeName[33]; @@ -858,13 +858,13 @@ void Map::load(int mapId) { fText.close(); // Load the monster/object data - Common::String mobName = Common::String::format("maze%c%03u.mob", + Common::String mobName = Common::String::format("maze%c%03d.mob", (mapId >= 100) ? 'x' : '0', mapId); File mobFile(mobName); _mobData.synchronize(mobFile, _isOutdoors, _monsterData); mobFile.close(); - Common::String headName = Common::String::format("aaze%c%03u.hed", + Common::String headName = Common::String::format("aaze%c%03d.hed", (mapId >= 100) ? 'x' : '0', mapId); File headFile(headName); _headData.synchronize(headFile); @@ -895,7 +895,7 @@ void Map::load(int mapId) { // TODO: Switch setting flags that don't seem to ever be used // Reload the monster data for the main maze that we're loading - Common::String filename = Common::String::format("maze%c%03u.mob", + Common::String filename = Common::String::format("maze%c%03d.mob", (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); File mobFile(filename, *_vm->_saves); _mobData.synchronize(mobFile, _isOutdoors, _monsterData); @@ -926,7 +926,7 @@ void Map::load(int mapId) { for (uint i = 0; i < _mobData._monsters.size(); ++i, ++monsterNum) { MonsterStruct &monsterStruct = _monsterData[i]; int monsterImgNum = monsterStruct._imageNumber; - filename = Common::String::format("%03u.mon", monsterImgNum); + filename = Common::String::format("%03d.mon", monsterImgNum); if (!monsterImgNums[monsterImgNum]) { _mobData._monsters[i]._sprites.load(filename); @@ -935,7 +935,7 @@ void Map::load(int mapId) { monsterImgNums[monsterImgNum] - 1]._sprites; } - filename = Common::String::format("%03u.att", monsterImgNum); + filename = Common::String::format("%03d.att", monsterImgNum); if (!monsterImgNums[monsterImgNum]) { _mobData._monsters[i]._attackSprites.load(filename); monsterImgNums[monsterImgNum] = monsterNum; @@ -947,7 +947,7 @@ void Map::load(int mapId) { // Load wall picture sprite resources for (uint i = 0; i < _mobData._wallItems.size(); ++i) { - filename = Common::String::format("%03u.pic", _mobData._wallItems[i]._refId); + filename = Common::String::format("%03d.pic", _mobData._wallItems[i]._refId); _mobData._wallItems[i]._sprites.load(filename); } } diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index 36bb7bda1a..404e3492a2 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -103,8 +103,9 @@ void SavesManager::reset() { Common::MemoryWriteStreamDynamic saveFile(DisposeAfterUse::YES); Common::File fIn; - for (int i = 0; i <= 5; ++i) { - Common::String filename = prefix + Common::String::format("2A%dC", i); + const int RESOURCES[6] = { 0x2A0C, 0x2A1C, 0x2A2C, 0x2A3C, 0x284C, 0x2A5C }; + for (int i = 0; i < 6; ++i) { + Common::String filename = prefix + Common::String::format("%.4x", RESOURCES[i]); if (fIn.exists(filename)) { // Read in the next resource fIn.open(filename); -- cgit v1.2.3 From 03952cd9d353c4af393da7ffeb524bcdb5746f34 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 8 Jan 2015 20:23:54 -0500 Subject: XEEN: Fix to load correct default savegame --- engines/xeen/saves.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index 404e3492a2..e6bfa80e09 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -99,7 +99,7 @@ void SavesManager::load(Common::SeekableReadStream *stream) { * Sets up the dynamic data for the game for a new game */ void SavesManager::reset() { - Common::String prefix = _vm->getGameID() == GType_Clouds ? "xeen|" : "dark|"; + Common::String prefix = _vm->getGameID() != GType_DarkSide ? "xeen|" : "dark|"; Common::MemoryWriteStreamDynamic saveFile(DisposeAfterUse::YES); Common::File fIn; -- cgit v1.2.3 From 00ef21e2a22dc84531d325bc95734b63b5c7daed Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 8 Jan 2015 23:02:46 -0500 Subject: XEEN: Fixed monster/object data merging and sprite loading --- engines/xeen/map.cpp | 174 +++++++++++++++++++++++++-------------------------- engines/xeen/map.h | 30 ++++++--- 2 files changed, 108 insertions(+), 96 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 63d5542d84..52dbc839a0 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -622,9 +622,10 @@ bool MobStruct::synchronize(Common::SeekableReadStream &s) { MazeObject::MazeObject() { _id = 0; _frame = 0; - _refId = 0; + _spriteId = 0; _direction = DIR_NORTH; _flipped = false; + _sprites = nullptr; } /*------------------------------------------------------------------------*/ @@ -632,17 +633,21 @@ MazeObject::MazeObject() { MazeMonster::MazeMonster() { _frame = 0; _id = 0; - _refId = 0; + _spriteId = 0; _hp = 0; _effect1 = _effect2 = 0; _effect3 = 0; + _sprites = nullptr; + _attackSprites = nullptr; } /*------------------------------------------------------------------------*/ MazeWallItem::MazeWallItem() { _id = 0; + _spriteId = 0; _direction = DIR_NORTH; + _sprites = nullptr; } /*------------------------------------------------------------------------*/ @@ -652,76 +657,83 @@ MonsterObjectData::MonsterObjectData(XeenEngine *vm): _vm(vm) { void MonsterObjectData::synchronize(Common::SeekableReadStream &s, bool isOutdoors, MonsterData monsterData) { + _objectSprites.clear(); + _monsterSprites.clear(); + _monsterAttackSprites.clear(); + _wallItemSprites.clear(); _objects.clear(); _monsters.clear(); _wallItems.clear(); - Common::Array<int> objectSprites; - Common::Array<int> monsterIds; - Common::Array<int> wallPicIds; - Common::Array<MobStruct> objData; - Common::Array<MobStruct> monData; - Common::Array<MobStruct> wallItemData; + + Common::Array<MobStruct> mobStructs; byte b; for (int i = 0; i < 16; ++i) { if ((b = s.readByte()) != 0xff) - objectSprites.push_back(b); + _objectSprites.push_back(SpriteResourceEntry(b)); } for (int i = 0; i < 16; ++i) { if ((b = s.readByte()) != 0xff) - monsterIds.push_back(b); + _monsterSprites.push_back(SpriteResourceEntry(b)); } for (int i = 0; i < 16; ++i) { if ((b = s.readByte()) != 0xff) - wallPicIds.push_back(b); + _wallItemSprites.push_back(SpriteResourceEntry(b)); } + // Merge together object data MobStruct mobStruct; - while (mobStruct.synchronize(s)) - objData.push_back(mobStruct); - while (mobStruct.synchronize(s)) - monData.push_back(mobStruct); - if (!isOutdoors) { - while (mobStruct.synchronize(s)) - wallItemData.push_back(mobStruct); - } - - // Merge up objects - _objects.resize(objData.size()); - for (uint i = 0; i < objData.size(); ++i) { - MazeObject &dest = _objects[i]; - dest._position = objData[i]._pos; - dest._id = objData[i]._id; - dest._refId = objectSprites[dest._id]; - dest._direction = objData[i]._direction; - dest._frame = 100; - } - - // merge up monsters - _monsters.resize(monData.size()); - for (uint i = 0; i < monData.size(); ++i) { - MazeMonster &dest = _monsters[i]; - dest._position = monData[i]._pos; - dest._id = monData[i]._id; - dest._refId = monsterIds[dest._id]; - - MonsterStruct &mon = monsterData[dest._refId]; - dest._hp = mon._hp; - dest._frame = _vm->getRandomNumber(7); - dest._effect1 = dest._effect2 = mon._animationEffect; - if (mon._animationEffect) - dest._effect3 = _vm->getRandomNumber(7); - } + mobStruct.synchronize(s); + do { + MazeObject obj; + obj._position = mobStruct._pos; + obj._id = mobStruct._id; + obj._direction = mobStruct._direction; + obj._frame = 100; + obj._spriteId = _objectSprites[obj._id]._spriteId; + obj._sprites = &_objectSprites[obj._id]._sprites; + + _objects.push_back(obj); + mobStruct.synchronize(s); + } while (mobStruct._id != 255 || mobStruct._pos.x != -1); + + // Merge together monster data + mobStruct.synchronize(s); + do { + MazeMonster mon; + mon._position = mobStruct._pos; + mon._id = mobStruct._id; + mon._spriteId = _monsterSprites[mon._id]._spriteId; + mon._sprites = &_monsterSprites[mon._id]._sprites; + mon._attackSprites = &_monsterSprites[mon._id]._attackSprites; + + MonsterStruct &md = monsterData[mon._spriteId]; + mon._hp = md._hp; + mon._frame = _vm->getRandomNumber(7); + mon._effect1 = mon._effect2 = md._animationEffect; + if (md._animationEffect) + mon._effect3 = _vm->getRandomNumber(7); + + _monsters.push_back(mon); + mobStruct.synchronize(s); + } while (mobStruct._id != 255 || mobStruct._pos.x != -1); + + // Merge together wall item data + mobStruct.synchronize(s); + do { + if (mobStruct._id < (int)_wallItemSprites.size()) { + MazeWallItem wi; + wi._position = mobStruct._pos; + wi._id = mobStruct._id; + wi._direction = mobStruct._direction; + wi._spriteId = _wallItemSprites[wi._id]._spriteId; + wi._sprites = &_wallItemSprites[wi._id]._sprites; + + _wallItems.push_back(wi); + } - // Merge up wall items - _wallItems.resize(1); - for (uint i = 0; i < wallItemData.size(); ++i) { - MazeWallItem &dest = _wallItems[i]; - dest._position = wallItemData[i]._pos; - dest._id = wallItemData[i]._id; - dest._refId = wallPicIds[dest._id]; - dest._direction = wallItemData[i]._direction; - } + mobStruct.synchronize(s); + } while (mobStruct._id != 255 || mobStruct._pos.x != -1); } /*------------------------------------------------------------------------*/ @@ -893,7 +905,7 @@ void Map::load(int mapId) { } // TODO: Switch setting flags that don't seem to ever be used - + // Reload the monster data for the main maze that we're loading Common::String filename = Common::String::format("maze%c%03d.mob", (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); @@ -902,53 +914,37 @@ void Map::load(int mapId) { mobFile.close(); // Load sprites for the objects - for (uint i = 0; i < _mobData._objects.size(); ++i) { - if (_vm->_party._cloudsEnd && _mobData._objects[i]._refId == 85 && + for (uint i = 0; i < _mobData._objectSprites.size(); ++i) { + if (_vm->_party._cloudsEnd && _mobData._objectSprites[i]._spriteId == 85 && _vm->_party._mazeId == 27 && isDarkCc) { // TODO: Flags set that don't seem to be used } else if (_vm->_party._mazeId == 12 && _vm->_party._gameFlags[43] && - _mobData._objects[i]._refId == 118 && !isDarkCc) { + _mobData._objectSprites[i]._spriteId == 118 && !isDarkCc) { filename = "085.obj"; - _mobData._objects[0]._id = 85; + _mobData._objectSprites[0]._spriteId = 85; } else { - filename = Common::String::format("%03d.%cbj", _mobData._objects[i]._refId, - _mobData._objects[i]._refId >= 100 ? 'o' : '0'); + filename = Common::String::format("%03d.%cbj", + _mobData._objectSprites[i]._spriteId, + _mobData._objectSprites[i]._spriteId >= 100 ? '0' : 'o'); } // Read in the object sprites - _mobData._objects[i]._sprites.load(filename); + _mobData._objectSprites[i]._sprites.load(filename); } - // Load sprite resources for monster standard and attack animations - int monsterNum = 1; - int monsterImgNums[95]; - Common::fill(&monsterImgNums[0], &monsterImgNums[95], 0); - for (uint i = 0; i < _mobData._monsters.size(); ++i, ++monsterNum) { - MonsterStruct &monsterStruct = _monsterData[i]; - int monsterImgNum = monsterStruct._imageNumber; - filename = Common::String::format("%03d.mon", monsterImgNum); - - if (!monsterImgNums[monsterImgNum]) { - _mobData._monsters[i]._sprites.load(filename); - } else { - _mobData._monsters[i]._sprites = _mobData._monsters[ - monsterImgNums[monsterImgNum] - 1]._sprites; - } + // Load sprites for the monsters + for (uint i = 0; i < _mobData._monsterSprites.size(); ++i) { + filename = Common::String::format("%03d.mon", _mobData._objectSprites[i]._spriteId); + _mobData._monsterSprites[i]._sprites.load(filename); - filename = Common::String::format("%03d.att", monsterImgNum); - if (!monsterImgNums[monsterImgNum]) { - _mobData._monsters[i]._attackSprites.load(filename); - monsterImgNums[monsterImgNum] = monsterNum; - } else { - _mobData._monsters[i]._attackSprites = _mobData._monsters[ - monsterImgNums[monsterImgNum] - 1]._attackSprites;; - } + filename = Common::String::format("%03d.att", _mobData._objectSprites[i]._spriteId); + _mobData._monsterSprites[i]._attackSprites.load(filename); } // Load wall picture sprite resources - for (uint i = 0; i < _mobData._wallItems.size(); ++i) { - filename = Common::String::format("%03d.pic", _mobData._wallItems[i]._refId); - _mobData._wallItems[i]._sprites.load(filename); + for (uint i = 0; i < _mobData._wallItemSprites.size(); ++i) { + filename = Common::String::format("%03d.pic", _mobData._wallItems[i]._spriteId); + _mobData._wallItemSprites[i]._sprites.load(filename); } } diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 7c0344b9a4..1d11bdcfaa 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -204,10 +204,10 @@ public: Common::Point _position; int _id; int _frame; - int _refId; + int _spriteId; Direction _direction; bool _flipped; - SpriteResource _sprites; + SpriteResource *_sprites; MazeObject(); }; @@ -216,12 +216,12 @@ struct MazeMonster { Common::Point _position; int _frame; int _id; - int _refId; + int _spriteId; int _hp; int _effect1, _effect2; int _effect3; - SpriteResource _sprites; - SpriteResource _attackSprites; + SpriteResource *_sprites; + SpriteResource *_attackSprites; MazeMonster(); }; @@ -230,16 +230,32 @@ class MazeWallItem { public: Common::Point _position; int _id; - int _refId; + int _spriteId; Direction _direction; - SpriteResource _sprites; + SpriteResource *_sprites; public: MazeWallItem(); }; +class Map; + class MonsterObjectData { + friend class Map; +public: + struct SpriteResourceEntry { + int _spriteId; + SpriteResource _sprites; + SpriteResource _attackSprites; + + SpriteResourceEntry() { _spriteId = -1; } + SpriteResourceEntry(int spriteId): _spriteId(spriteId) { } + }; private: XeenEngine *_vm; + Common::Array<SpriteResourceEntry> _objectSprites; + Common::Array<SpriteResourceEntry> _monsterSprites; + Common::Array<SpriteResourceEntry> _monsterAttackSprites; + Common::Array<SpriteResourceEntry> _wallItemSprites; public: Common::Array<MazeObject> _objects; Common::Array<MazeMonster> _monsters; -- cgit v1.2.3 From 08e64d0a6146b9fde774467cc1906f230571f72d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 9 Jan 2015 08:29:28 -0500 Subject: XEEN: Added indoor/outdoor draw structure lists --- engines/xeen/interface.cpp | 312 +++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/interface.h | 25 ++++ engines/xeen/sprites.h | 3 +- 3 files changed, 339 insertions(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index c27cdb9bd3..6f0d4d580f 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -27,6 +27,318 @@ namespace Xeen { +OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]) { + _data[0] = DrawStruct(0, 8, 8); + _data[1] = DrawStruct(1, 8, 25); + _data[2] = DrawStruct(0, 8, 67); + _data[3] = DrawStruct(0, 8, 67); + _data[4] = DrawStruct(0, 38, 67); + _data[5] = DrawStruct(0, 84, 67); + _data[6] = DrawStruct(0, 134, 67); + _data[7] = DrawStruct(0, 117, 67); + _data[8] = DrawStruct(0, 117, 67); + _data[9] = DrawStruct(0, 103, 67); + _data[10] = DrawStruct(0, 8, 73); + _data[11] = DrawStruct(0, 8, 73); + _data[12] = DrawStruct(0, 30, 73); + _data[13] = DrawStruct(0, 181, 73); + _data[14] = DrawStruct(0, 154, 73); + _data[15] = DrawStruct(0, 129, 73); + _data[16] = DrawStruct(0, 87, 73); + _data[17] = DrawStruct(0, 8, 81); + _data[18] = DrawStruct(0, 8, 81); + _data[19] = DrawStruct(0, 202, 81); + _data[20] = DrawStruct(0, 145, 81); + _data[21] = DrawStruct(0, 63, 81); + _data[22] = DrawStruct(0, 8, 93); + _data[23] = DrawStruct(0, 169, 93); + _data[24] = DrawStruct(0, 31, 93); + _data[25] = DrawStruct(0, 8, 109); + _data[26] = DrawStruct(0, 201, 109); + _data[27] = DrawStruct(0, 8, 109); + _data[28] = DrawStruct(1, 65472, 61, 14, SPRFLAG_2000); + _data[29] = DrawStruct(1, 65496, 61, 14, 0); + _data[30] = DrawStruct(1, 65520, 61, 14, 0); + _data[31] = DrawStruct(1, 8, 61, 14, 0); + _data[32] = DrawStruct(1, 128, 61, 14, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000); + _data[33] = DrawStruct(1, 104, 61, 14, SPRFLAG_HORIZ_FLIPPED); + _data[34] = DrawStruct(1, 80, 61, 14, SPRFLAG_HORIZ_FLIPPED); + _data[35] = DrawStruct(1, 56, 61, 14, SPRFLAG_HORIZ_FLIPPED); + _data[36] = DrawStruct(1, 32, 61, 14, 0); + _data[37] = DrawStruct(0, 65527, 61, 14, 0); + _data[38] = DrawStruct(0, 65478, 61, 14, 0); + _data[39] = DrawStruct(0, 40, 61, 14, 0); + _data[40] = DrawStruct(0, 65454, 61, 14, 0); + _data[41] = DrawStruct(0, 64, 61, 14, 0); + _data[42] = DrawStruct(0, 65495, 61, 14, 0); + _data[43] = DrawStruct(0, 65510, 61, 14, 0); + _data[44] = DrawStruct(0, 65502, 61, 14, 0); + _data[45] = DrawStruct(0, 65520, 61, 14, 0); + _data[46] = DrawStruct(0, 23, 61, 14, 0); + _data[47] = DrawStruct(0, 16, 61, 14, 0); + _data[48] = DrawStruct(0, 65478, 61, 14, 0); + _data[49] = DrawStruct(0, 40, 61, 14, 0); + _data[50] = DrawStruct(0, 65519, 61, 14, 0); + _data[51] = DrawStruct(0, 65535, 58, 14, 0); + _data[52] = DrawStruct(0, 65527, 58, 14, 0); + _data[53] = DrawStruct(0, 72, 58, 12, 0); + _data[54] = DrawStruct(0, 72, 58, 12, SPRFLAG_HORIZ_FLIPPED); + _data[55] = DrawStruct(0, 69, 63, 12, 0); + _data[56] = DrawStruct(0, 75, 63, 12, SPRFLAG_HORIZ_FLIPPED); + _data[57] = DrawStruct(0, 73, 53, 12, 0); + _data[58] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED); + _data[59] = DrawStruct(0, 80, 57, 12, 0); + _data[60] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED); + _data[61] = DrawStruct(2, 65525, 54, 8, 0); + _data[62] = DrawStruct(1, 65515, 54, 11, 0); + _data[63] = DrawStruct(2, 165, 54, 8, SPRFLAG_HORIZ_FLIPPED); + _data[64] = DrawStruct(1, 86, 54, 11, SPRFLAG_HORIZ_FLIPPED); + _data[65] = DrawStruct(1, 33, 54, 11, 0); + _data[66] = DrawStruct(0, 65528, 54, 12, 0); + _data[67] = DrawStruct(0, 65463, 54, 12, 0); + _data[68] = DrawStruct(0, 57, 54, 12, 0); + _data[69] = DrawStruct(0, 65471, 54, 12, 0); + _data[70] = DrawStruct(0, 65455, 54, 12, 0); + _data[71] = DrawStruct(0, 49, 54, 12, 0); + _data[72] = DrawStruct(0, 65, 54, 12, 0); + _data[73] = DrawStruct(0, 65512, 54, 12, 0); + _data[74] = DrawStruct(0, 9, 50, 12, 0); + _data[75] = DrawStruct(0, 65528, 50, 12, 0); + _data[76] = DrawStruct(0, 72, 53, 8, 0); + _data[77] = DrawStruct(0, 72, 53, 8, SPRFLAG_HORIZ_FLIPPED); + _data[78] = DrawStruct(0, 77, 58, 8, 0); + _data[79] = DrawStruct(0, 67, 58, 8, SPRFLAG_HORIZ_FLIPPED); + _data[80] = DrawStruct(0, 81, 47, 8, 0); + _data[81] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED); + _data[82] = DrawStruct(0, 94, 52, 8, 0); + _data[83] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED); + _data[84] = DrawStruct(2, 8, 40); + _data[85] = DrawStruct(2, 146, 40, 0, SPRFLAG_HORIZ_FLIPPED); + _data[86] = DrawStruct(1, 32, 40, 6, 0); + _data[87] = DrawStruct(0, 65529, 30, 7, 0); + _data[88] = DrawStruct(0, 65424, 30, 7, SPRFLAG_2000); + _data[89] = DrawStruct(0, 98, 30, 7, SPRFLAG_2000); + _data[90] = DrawStruct(0, 65424, 30, 8, SPRFLAG_2000); + _data[91] = DrawStruct(0, 98, 30, 8, SPRFLAG_2000); + _data[92] = DrawStruct(0, 65498, 30, 8, 0); + _data[93] = DrawStruct(0, 25, 30, 8, 0); + _data[94] = DrawStruct(0, 65529, 30, 8, 0); + _data[95] = DrawStruct(0, 72, 48, 4, 0); + _data[96] = DrawStruct(0, 72, 48, 4, SPRFLAG_HORIZ_FLIPPED); + _data[97] = DrawStruct(0, 85, 53, 4, 0); + _data[98] = DrawStruct(0, 59, 53, 4, SPRFLAG_HORIZ_FLIPPED); + _data[99] = DrawStruct(0, 89, 41, 4, 0); + _data[100] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED); + _data[101] = DrawStruct(0, 106, 47, 4, 0); + _data[102] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED); + _data[103] = DrawStruct(0, 8, 24); + _data[104] = DrawStruct(0, 169, 24, 0, SPRFLAG_HORIZ_FLIPPED); + _data[105] = DrawStruct(1, 32, 24); + _data[106] = DrawStruct(0, 65513, 40, 0, SPRFLAG_2000); + _data[107] = DrawStruct(0, 200, 40, 0, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000); + _data[108] = DrawStruct(0, 8, 47); + _data[109] = DrawStruct(0, 169, 47, 0, SPRFLAG_HORIZ_FLIPPED); + _data[110] = DrawStruct(1, 65480, 65532, 32768, SPRFLAG_4000 | SPRFLAG_2000); + _data[111] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[112] = DrawStruct(0, 65469, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[113] = DrawStruct(0, 44, 73); + _data[114] = DrawStruct(0, 44, 73); + _data[115] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[116] = DrawStruct(0, 169, 73); + _data[117] = DrawStruct(0, 169, 73); + _data[118] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[119] = DrawStruct(0, 110, 73); + _data[120] = DrawStruct(0, 110, 73); + _data[121] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[122] = DrawStruct(0, 110, 73); + _data[123] = DrawStruct(0, 110, 73); + _data[124] = DrawStruct(0, 72, 43); + _data[125] = DrawStruct(0, 72, 43, 0, SPRFLAG_HORIZ_FLIPPED); + _data[126] = DrawStruct(0, 93, 48); + _data[127] = DrawStruct(0, 51, 48, 0, SPRFLAG_HORIZ_FLIPPED); + _data[128] = DrawStruct(0, 97, 36); + _data[129] = DrawStruct(0, 47, 36, 0, SPRFLAG_HORIZ_FLIPPED); + _data[130] = DrawStruct(0, 118, 42); + _data[131] = DrawStruct(0, 26, 42, 0, SPRFLAG_HORIZ_FLIPPED); +} + +/*------------------------------------------------------------------------*/ + +IndoorDrawList::IndoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]) { + _data[0] = DrawStruct(0, 8, 8); + _data[1] = DrawStruct(1, 8, 25); + _data[2] = DrawStruct(0, 8, 67); + _data[3] = DrawStruct(0, 8, 67); + _data[4] = DrawStruct(0, 38, 67); + _data[5] = DrawStruct(0, 84, 67); + _data[6] = DrawStruct(0, 134, 67); + _data[7] = DrawStruct(0, 117, 67); + _data[8] = DrawStruct(0, 117, 67); + _data[9] = DrawStruct(0, 103, 67); + _data[10] = DrawStruct(0, 8, 73); + _data[11] = DrawStruct(0, 8, 73); + _data[12] = DrawStruct(0, 30, 73); + _data[13] = DrawStruct(0, 181, 73); + _data[14] = DrawStruct(0, 154, 73); + _data[15] = DrawStruct(0, 129, 73); + _data[16] = DrawStruct(0, 87, 73); + _data[17] = DrawStruct(0, 8, 81); + _data[18] = DrawStruct(0, 8, 81); + _data[19] = DrawStruct(0, 202, 81); + _data[20] = DrawStruct(0, 145, 81); + _data[21] = DrawStruct(0, 63, 81); + _data[22] = DrawStruct(0, 8, 93); + _data[23] = DrawStruct(0, 169, 93); + _data[24] = DrawStruct(0, 31, 93); + _data[25] = DrawStruct(0, 8, 109); + _data[26] = DrawStruct(0, 201, 109); + _data[27] = DrawStruct(0, 8, 109); + _data[28] = DrawStruct(7, 8, 64); + _data[29] = DrawStruct(22, 32, 60); + _data[30] = DrawStruct(20, 56, 60); + _data[31] = DrawStruct(18, 80, 60); + _data[32] = DrawStruct(16, 104, 60); + _data[33] = DrawStruct(23, 152, 60, 0, SPRFLAG_HORIZ_FLIPPED); + _data[34] = DrawStruct(21, 144, 60, 0, SPRFLAG_HORIZ_FLIPPED); + _data[35] = DrawStruct(19, 131, 60, 0, SPRFLAG_HORIZ_FLIPPED); + _data[36] = DrawStruct(17, 120, 60, 0, SPRFLAG_HORIZ_FLIPPED); + _data[37] = DrawStruct(14, 8, 60); + _data[38] = DrawStruct(12, 32, 60); + _data[39] = DrawStruct(10, 56, 60); + _data[40] = DrawStruct(14, 80, 60); + _data[41] = DrawStruct(14, 104, 60); + _data[42] = DrawStruct(14, 128, 60); + _data[43] = DrawStruct(14, 152, 60); + _data[44] = DrawStruct(8, 176, 60); + _data[45] = DrawStruct(8, 200, 60); + _data[46] = DrawStruct(0, 65472, 61, 14, 0); + _data[47] = DrawStruct(0, 65496, 61, 14, 0); + _data[48] = DrawStruct(0, 65520, 61, 14, 0); + _data[49] = DrawStruct(0, 8, 61, 14, 0); + _data[50] = DrawStruct(0, 32, 61, 14, 0); + _data[51] = DrawStruct(0, 56, 61, 14, 0); + _data[52] = DrawStruct(0, 80, 61, 14, 0); + _data[53] = DrawStruct(0, 104, 61, 14, 0); + _data[54] = DrawStruct(0, 128, 61, 14, 0); + _data[55] = DrawStruct(0, 65527, 58, 14, 0); + _data[56] = DrawStruct(0, 65502, 58, 14, 0); + _data[57] = DrawStruct(0, 16, 58, 14, 0); + _data[58] = DrawStruct(0, 65478, 58, 14, 0); + _data[59] = DrawStruct(0, 40, 58, 14, 0); + _data[60] = DrawStruct(0, 65495, 58, 14, 0); + _data[61] = DrawStruct(0, 65510, 58, 14, 0); + _data[62] = DrawStruct(0, 65502, 58, 14, 0); + _data[63] = DrawStruct(0, 65520, 58, 14, 0); + _data[64] = DrawStruct(0, 23, 58, 14, 0); + _data[65] = DrawStruct(0, 16, 58, 14, 0); + _data[66] = DrawStruct(0, 65478, 58, 14, 0); + _data[67] = DrawStruct(0, 40, 58, 14, 0); + _data[68] = DrawStruct(0, 65519, 58, 14, 0); + _data[69] = DrawStruct(0, 65535, 58, 14, 0); + _data[70] = DrawStruct(0, 65527, 58, 14, 0); + _data[71] = DrawStruct(14, 8, 58); + _data[72] = DrawStruct(12, 8, 55); + _data[73] = DrawStruct(10, 32, 52); + _data[74] = DrawStruct(14, 88, 52); + _data[75] = DrawStruct(14, 128, 52, 0, SPRFLAG_HORIZ_FLIPPED); + _data[76] = DrawStruct(14, 152, 52, 0, SPRFLAG_HORIZ_FLIPPED); + _data[77] = DrawStruct(0, 176, 55, 0, SPRFLAG_HORIZ_FLIPPED); + _data[78] = DrawStruct(0, 200, 58, 0, SPRFLAG_HORIZ_FLIPPED); + _data[79] = DrawStruct(0, 72, 58, 12, 0); + _data[80] = DrawStruct(0, 72, 58, 12, SPRFLAG_HORIZ_FLIPPED); + _data[81] = DrawStruct(0, 69, 63, 12, 0); + _data[82] = DrawStruct(0, 75, 63, 12, SPRFLAG_HORIZ_FLIPPED); + _data[83] = DrawStruct(0, 73, 53, 12, 0); + _data[84] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED); + _data[85] = DrawStruct(0, 80, 57, 12, 0); + _data[86] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED); + _data[87] = DrawStruct(7, 65512, 52, 0, SPRFLAG_2000); + _data[88] = DrawStruct(7, 32, 52); + _data[89] = DrawStruct(7, 88, 52); + _data[90] = DrawStruct(0, 144, 52); + _data[91] = DrawStruct(0, 200, 52, 0, SPRFLAG_2000); + _data[92] = DrawStruct(0, 65457, 52, 11, SPRFLAG_2000); + _data[93] = DrawStruct(0, 65509, 52, 11, 0); + _data[94] = DrawStruct(0, 32, 52, 11, 0); + _data[95] = DrawStruct(0, 89, 52, 11, 0); + _data[96] = DrawStruct(0, 145, 52, 11, SPRFLAG_2000); + _data[97] = DrawStruct(0, 65528, 50, 12, 0); + _data[98] = DrawStruct(0, 65471, 50, 12, 0); + _data[99] = DrawStruct(0, 49, 50, 12, 0); + _data[100] = DrawStruct(0, 65471, 50, 12, 0); + _data[101] = DrawStruct(0, 65455, 50, 12, 0); + _data[102] = DrawStruct(0, 49, 50, 12, 0); + _data[103] = DrawStruct(0, 65, 50, 12, 0); + _data[104] = DrawStruct(0, 65512, 50, 12, 0); + _data[105] = DrawStruct(0, 9, 50, 12, 0); + _data[106] = DrawStruct(0, 65528, 50, 12, 0); + _data[107] = DrawStruct(7, 8, 48); + _data[108] = DrawStruct(7, 64, 40); + _data[109] = DrawStruct(6, 144, 40, 0, SPRFLAG_HORIZ_FLIPPED); + _data[110] = DrawStruct(6, 200, 48, 0, SPRFLAG_HORIZ_FLIPPED); + _data[111] = DrawStruct(0, 72, 53, 8, 0); + _data[112] = DrawStruct(0, 72, 53, 8, SPRFLAG_HORIZ_FLIPPED); + _data[113] = DrawStruct(0, 77, 58, 8, 0); + _data[114] = DrawStruct(0, 67, 58, 8, SPRFLAG_HORIZ_FLIPPED); + _data[115] = DrawStruct(0, 81, 47, 8, 0); + _data[116] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED); + _data[117] = DrawStruct(0, 94, 52, 8, 0); + _data[118] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED); + _data[119] = DrawStruct(6, 65496, 40, 0, SPRFLAG_2000); + _data[120] = DrawStruct(6, 64, 40); + _data[121] = DrawStruct(0, 168, 40, 0, SPRFLAG_2000); + _data[122] = DrawStruct(0, 65464, 40, 6, SPRFLAG_2000); + _data[123] = DrawStruct(0, 32, 40, 6, 0); + _data[124] = DrawStruct(0, 137, 40, 6, SPRFLAG_2000); + _data[125] = DrawStruct(0, 65529, 25, 7, 0); + _data[126] = DrawStruct(0, 65424, 25, 7, SPRFLAG_2000); + _data[127] = DrawStruct(0, 98, 25, 7, SPRFLAG_2000); + _data[128] = DrawStruct(0, 65424, 29, 8, SPRFLAG_2000); + _data[129] = DrawStruct(0, 98, 29, 8, SPRFLAG_2000); + _data[130] = DrawStruct(0, 65498, 29, 8, 0); + _data[131] = DrawStruct(0, 25, 29, 8, 0); + _data[132] = DrawStruct(0, 65529, 29, 8, 0); + _data[133] = DrawStruct(6, 32, 24); + _data[134] = DrawStruct(0, 168, 24, 0, SPRFLAG_HORIZ_FLIPPED); + _data[135] = DrawStruct(0, 72, 48, 4, 0); + _data[136] = DrawStruct(0, 72, 48, 4, SPRFLAG_HORIZ_FLIPPED); + _data[137] = DrawStruct(0, 85, 53, 4, 0); + _data[138] = DrawStruct(0, 59, 53, 4, SPRFLAG_HORIZ_FLIPPED); + _data[139] = DrawStruct(0, 89, 41, 4, 0); + _data[140] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED); + _data[141] = DrawStruct(0, 106, 47, 4, 0); + _data[142] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED); + _data[143] = DrawStruct(0, 65400, 24, 0, SPRFLAG_2000); + _data[144] = DrawStruct(0, 8, 12); + _data[145] = DrawStruct(0, 32, 24); + _data[146] = DrawStruct(0, 200, 12, 0, SPRFLAG_HORIZ_FLIPPED); + _data[147] = DrawStruct(0, 200, 24, 0, SPRFLAG_2000); + _data[148] = DrawStruct(0, 32, 24); + _data[149] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[150] = DrawStruct(0, 65469, 10, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[151] = DrawStruct(0, 44, 73); + _data[152] = DrawStruct(0, 44, 73); + _data[153] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[154] = DrawStruct(0, 169, 73); + _data[155] = DrawStruct(0, 169, 73); + _data[156] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[157] = DrawStruct(0, 110, 73); + _data[158] = DrawStruct(0, 110, 73); + _data[159] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[160] = DrawStruct(0, 110, 73); + _data[161] = DrawStruct(0, 110, 73); + _data[162] = DrawStruct(0, 72, 43); + _data[163] = DrawStruct(0, 72, 43, 0, SPRFLAG_HORIZ_FLIPPED); + _data[164] = DrawStruct(0, 93, 48); + _data[165] = DrawStruct(0, 51, 48, 0, SPRFLAG_HORIZ_FLIPPED); + _data[166] = DrawStruct(0, 97, 36); + _data[167] = DrawStruct(0, 47, 36, 0, SPRFLAG_HORIZ_FLIPPED); + _data[168] = DrawStruct(0, 118, 42); + _data[169] = DrawStruct(0, 26, 42, 0, SPRFLAG_HORIZ_FLIPPED); +} + +/*------------------------------------------------------------------------*/ + Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr); _batUIFrame = 0; diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 475e71bbce..60250bd8e8 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -32,6 +32,29 @@ namespace Xeen { class XeenEngine; +class OutdoorDrawList { +public: + DrawStruct _data[132]; + DrawStruct &_skySprite; + DrawStruct &_groundSprite; +public: + OutdoorDrawList(); + + DrawStruct &operator[](int idx) { return _data[idx]; } +}; + +class IndoorDrawList { +public: + DrawStruct _data[170]; + DrawStruct &_skySprite; + DrawStruct &_groundSprite; +public: + IndoorDrawList(); + + DrawStruct &operator[](int idx) { return _data[idx]; } +}; + + class Interface: public ButtonContainer { private: XeenEngine *_vm; @@ -49,6 +72,8 @@ private: SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; DrawStruct _faceDrawStructs[4]; DrawStruct _mainList[16]; + OutdoorDrawList _outdoorList; + IndoorDrawList _indoorList; int _combatCharIds[8]; int _batUIFrame; diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index 7f937abe8c..59c1ed1d48 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -33,7 +33,8 @@ namespace Xeen { class XeenEngine; -enum SpriteFlags { SPRFLAG_HORIZ_FLIPPED = 0x8000 }; +enum SpriteFlags { SPRFLAG_2000 = 0x2000, SPRFLAG_4000 = 0x4000, + SPRFLAG_HORIZ_FLIPPED = 0x8000 }; class SpriteResource { private: -- cgit v1.2.3 From 8f0c5543fbac066a9b0f216ae0747e6cff528a2c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 9 Jan 2015 22:27:48 -0500 Subject: XEEN: Beginning to implement setIndoorObjects --- engines/xeen/interface.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++---- engines/xeen/interface.h | 10 ++++-- engines/xeen/map.h | 2 +- engines/xeen/resources.cpp | 47 +++++++++++++++++++++++++++ engines/xeen/resources.h | 10 ++++++ 5 files changed, 140 insertions(+), 9 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 6f0d4d580f..e960b3d89a 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -164,7 +164,11 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2 /*------------------------------------------------------------------------*/ -IndoorDrawList::IndoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]) { +IndoorDrawList::IndoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]), + _objects0(_data[149]), _objects1(_data[125]), _objects2(_data[126]), + _objects3(_data[127]), _objects4(_data[97]), _objects5(_data[98]), + _objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]), + _objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]) { _data[0] = DrawStruct(0, 8, 8); _data[1] = DrawStruct(1, 8, 25); _data[2] = DrawStruct(0, 8, 67); @@ -360,6 +364,9 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { _flag1 = false; _flag2 = false; _tillMove = 0; + _objNumber = 0; + _objectFlag2 = _objectFlag3 = _objectFlag4 = _objectFlag5 = false; + _objectFlag6 = _objectFlag7 = _objectFlag8 = false; initDrawStructs(); } @@ -846,7 +853,7 @@ void Interface::addCharacterToRoster() { void Interface::draw3d(bool flag) { Screen &screen = *_vm->_screen; - EventsManager &events = *_vm->_events; +// EventsManager &events = *_vm->_events; if (!screen._windows[11]._enabled) return; @@ -869,12 +876,73 @@ void Interface::animate3d() { } -void Interface::setMonsters() { +void Interface::setIndoorsMonsters() { } -void Interface::setObjects() { +void Interface::setIndoorObjects() { + Common::Point mazePos = _vm->_party._mazePosition; + _objNumber = 0; + int objIndx = 0; + const int8 *posOffset = &SCREEN_POSITIONING[_vm->_party._mazeDirection * 48]; + Common::Point pt; + + // TODO: Fields loading + Common::Array<MazeObject> &objects = _vm->_map->_mobData._objects; + for (uint idx = 0; idx < objects.size(); ++idx) { + MazeObject &mazeObject = objects[idx]; + + // Determine which half of the X/Y lists to use + int listOffset; + if (_vm->_files->_isDarkCc) { + listOffset = mazeObject._spriteId == 47 ? 1 : 0; + } else { + listOffset = mazeObject._spriteId == 113 ? 1 : 0; + } + + // Position 1 + pt = Common::Point(mazePos.x + posOffset[2], mazePos.y + posOffset[194]); + if (pt == mazeObject._position && _indoorList._objects0._frame == -1) { + _indoorList._objects0._x = INDOOR_OBJECT_X[listOffset][0]; + _indoorList._objects0._y = INDOOR_OBJECT_Y[listOffset][0]; + _indoorList._objects0._frame = mazeObject._frame; + _indoorList._objects0._sprites = mazeObject._sprites; + _indoorList._objects0._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects0._flags |= SPRFLAG_HORIZ_FLIPPED; + _objNumber = idx; + } + + // Position 2 + pt = Common::Point(mazePos.x + posOffset[7], mazePos.y + posOffset[199]); + if (pt == mazeObject._position && !_objectFlag2 && _indoorList._objects1._frame == -1) { + _indoorList._objects1._x = INDOOR_OBJECT_X[listOffset][1]; + _indoorList._objects1._y = INDOOR_OBJECT_Y[listOffset][1]; + _indoorList._objects1._frame = mazeObject._frame; + _indoorList._objects1._sprites = mazeObject._sprites; + _indoorList._objects1._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects1._flags |= SPRFLAG_HORIZ_FLIPPED; + _objNumber = idx; + } + + // Position 3 + pt = Common::Point(mazePos.x + posOffset[5], mazePos.y + posOffset[197]); + if (pt == mazeObject._position && !_objectFlag2 && _indoorList._objects2._frame == -1) { + _indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][1]; + _indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][1]; + _indoorList._objects2._frame = mazeObject._frame; + _indoorList._objects2._sprites = mazeObject._sprites; + _indoorList._objects2._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects2._flags |= SPRFLAG_HORIZ_FLIPPED; + _objNumber = idx; + } + + // Position 4 onwards + // TODO: Also resolve usage of _objectFlag* flags + } } void Interface::setOutdoorsMonsters() { @@ -892,8 +960,8 @@ void Interface::startup() { animate3d(); if (_vm->_map->_isOutdoors) { - setMonsters(); - setObjects(); + setIndoorsMonsters(); + setIndoorObjects(); } else { setOutdoorsMonsters(); setOutdoorsObjects(); diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 60250bd8e8..5dc5e1ffbe 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -48,6 +48,9 @@ public: DrawStruct _data[170]; DrawStruct &_skySprite; DrawStruct &_groundSprite; + DrawStruct &_objects0, _objects1, _objects2, _objects3; + DrawStruct &_objects4, _objects5, _objects6, _objects7; + DrawStruct &_objects8, _objects9, _objects10, _objects11; public: IndoorDrawList(); @@ -95,6 +98,9 @@ private: bool _flag1; bool _flag2; byte _tillMove; + int _objNumber; + bool _objectFlag2, _objectFlag3, _objectFlag4, _objectFlag5; + bool _objectFlag6, _objectFlag7, _objectFlag8; void loadSprites(); @@ -114,9 +120,9 @@ private: void animate3d(); - void setMonsters(); + void setIndoorsMonsters(); - void setObjects(); + void setIndoorObjects(); void setOutdoorsMonsters(); diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 1d11bdcfaa..30c2c643df 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -285,7 +285,6 @@ private: XeenEngine *_vm; MazeData _mazeData[9]; Common::String _mazeName; - MonsterObjectData _mobData; HeadData _headData; SpriteResource _objPicSprites; MonsterData _monsterData; @@ -296,6 +295,7 @@ private: bool _stepped; public: bool _isOutdoors; + MonsterObjectData _mobData; public: Map(XeenEngine *vm); diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 3f59f3e1c9..35fa2cb2bf 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -303,4 +303,51 @@ const char *const PLEASE_WAIT = "\014""d\003""c\011""000" const char *const OOPS = "\003""c\011""000\013""002Oops..."; +const int8 SCREEN_POSITIONING[384] = { + -1, 0, 0, 0, 1, -1, 0, 0, 0, 1, -2, -1, -1, 0, 0, 0, + 1, 1, 2, -4, -3, -3, -2, -2, -1, -1, 0, 0, 0, 1, 1, 2, + 2, 3, 3, 4, -3, -2, -1, 0, 0, 1, 2, 3, -4, 4, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1, + 1, 0, 0, 0, -1, 1, 0, 0, 0, -1, 2, 1, 1, 0, 0, 0, + -1, -1, -2, 4, 3, 3, 2, 2, 1, 1, 0, 0, 0, -1, -1, -2, + -2, -3, -3, -4, 3, 2, 1, 0, 0, -1, -2, -3, 4, -4, 0, 0, + 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, + -3, -3, -3, -3, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, 0, -1, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1, + 1, 0, 0, 0, -1, 1, 0, 0, 0, -1, 2, 1, 1, 0, 0, 0, + -1, -1, -2, 4, 3, 3, 2, 2, 1, 1, 0, 0, 0, -1, -1, -2, + -2, -3, -3, -4, 3, 2, 1, 0, 0, -1, -2, -3, 4, -4, 0, 0, + 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, + -3, -3, -3, -3, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, 0, -1, + -1, 0, 0, 0, 1, -1, 0, 0, 0, 1, -2, -1, -1, 0, 0, 0, + 1, 1, 2, -4, -3, -3, -2, -2, -1, -1, 0, 0, 0, 1, 1, 2, + 2, 3, 3, 4, -3, -2, -1, 0, 0, 1, 2, 3, -4, 4, 0, 0, +}; + +const int INDOOR_OBJECT_X[2][12] = { + { 5, -7, -112, 98, -8, -65, 49, -9, -34, 16, -58, 40 }, + { -35, -35, -142, 68, -35, -95, 19, -35, -62, -14, -98, 16 } +}; + +const int INDOOR_OBJECT_Y[2][12] = { + { 2, 25, 25, 25, 50, 50, 50, 58, 58, 58, 58, 58 }, + { -65, -6, -6, -6, 36, 36, 36, 54, 54, 54, 54, 54 } +}; + +const int OUTDOOR_OBJECT_X[2][12] = { + { -5, -7, -112, 98, -8, -77, 61, -9, -43, 25, -74, 56 }, + { -35, -35, -142, 68, -35, -95, 19, -35, -62, -24, -98, 16 } +}; + +const int OUTDOOR_OBJECT_Y[2][12] = { + { 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 69 }, + { 70, 71, 72, 73, 74, 75, 90, 91, 92, 93, 94, 112 } +}; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 78104b233c..d8cc93b9f4 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -68,6 +68,16 @@ extern const char *const PLEASE_WAIT; extern const char *const OOPS; +extern const int8 SCREEN_POSITIONING[384]; + +extern const int INDOOR_OBJECT_X[2][12]; + +extern const int INDOOR_OBJECT_Y[2][12]; + +extern const int OUTDOOR_OBJECT_X[2][12]; + +extern const int OUTDOOR_OBJECT_Y[2][12]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From 49787629ffb86569faebd3155fd65c0cedea0bad Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 11 Jan 2015 08:54:42 -0500 Subject: XEEN: Various renamings --- engines/xeen/darkside/darkside_game.cpp | 4 +- engines/xeen/dialogs_options.cpp | 2 +- engines/xeen/interface.cpp | 16 ++-- engines/xeen/interface.h | 6 +- engines/xeen/map.cpp | 152 ++++++++++++++++++++++++++++++-- engines/xeen/map.h | 54 +++++++++++- engines/xeen/party.cpp | 4 +- engines/xeen/party.h | 4 +- engines/xeen/sound.h | 2 +- engines/xeen/xeen.cpp | 2 +- engines/xeen/xeen.h | 2 +- 11 files changed, 215 insertions(+), 33 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp index 30f54580e3..60cb69362a 100644 --- a/engines/xeen/darkside/darkside_game.cpp +++ b/engines/xeen/darkside/darkside_game.cpp @@ -220,8 +220,8 @@ void DarkSideEngine::showStartSequence() { pause(30); // TODO: More - _sound->playMusic(voc[0]); - _sound->playMusic(voc[1]); + _sound->playSong(voc[0]); + _sound->playSong(voc[1]); } } // End of namespace Xeen diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp index fb7366c5c7..8f02559837 100644 --- a/engines/xeen/dialogs_options.cpp +++ b/engines/xeen/dialogs_options.cpp @@ -54,7 +54,7 @@ void OptionsMenu::execute() { EventsManager &events = *_vm->_events; File newBright("newbrigh.m"); - _vm->_sound->playMusic(newBright); + _vm->_sound->playSong(newBright); screen._windows[GAME_WINDOW].setBounds(Common::Rect(72, 25, 248, 175)); diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index e960b3d89a..f952425d05 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -355,7 +355,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { _holyBonusUIFrame = 0; _heroismUIFrame = 0; _flipUIFrame = 0; - _isEarlyGame = false; + _newDay = false; _buttonsLoaded = false; _hiliteChar = -1; Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); @@ -411,7 +411,7 @@ void Interface::setup() { _vm->_party._activeParty[i] = _vm->_roster[_vm->_party._partyMembers[i]]; } - _isEarlyGame = _vm->_party._minutes >= 300; + _newDay = _vm->_party._minutes >= 300; } void Interface::manageCharacters(bool soundPlayed) { @@ -546,7 +546,7 @@ start: } else { screen.fadeOut(4); w.close(); - addCharacterToRoster(); + moveCharacterToRoster(); _vm->_saves->writeCharFile(); screen.fadeOut(4); flag = true; @@ -636,7 +636,7 @@ void Interface::assembleBorder() { // Draw UI element to indicate whether can spot hidden doors _borderSprites.draw(screen, - (_vm->_spotDoorsAllowed && _vm->_party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, + (_vm->_thinWall && _vm->_party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, Common::Point(194, 91)); _spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12; @@ -788,7 +788,7 @@ void Interface::charIconsPrint(bool updateFlag) { _vm->_party._partyCount); ++idx) { int charIndex = stateFlag ? _combatCharIds[idx] : idx; PlayerStruct &ps = _vm->_party._activeParty[charIndex]; - Condition charCondition = ps.findCondition(); + Condition charCondition = ps.worstCondition(); int charFrame = FACE_CONDITION_FRAMES[charCondition]; SpriteResource *sprites = (charFrame > 4 && !_charFaces[0].empty()) ? @@ -847,7 +847,7 @@ void Interface::drawViewBackground(int bgType) { } } -void Interface::addCharacterToRoster() { +void Interface::moveCharacterToRoster() { error("TODO"); } @@ -975,7 +975,7 @@ void Interface::startup() { for (int i = 1; i < 16; ++i) _mainList[i]._sprites = &_iconSprites; - setIconButtons(); + setMainButtons(); _tillMove = false; } @@ -992,7 +992,7 @@ void Interface::moveMonsters() { } -void Interface::setIconButtons() { +void Interface::setMainButtons() { clearButtons(); addButton(Common::Rect(235, 75, 259, 95), 83, &_iconSprites); diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 5dc5e1ffbe..3bb0fa7463 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -89,7 +89,7 @@ private: int _holyBonusUIFrame; int _heroismUIFrame; int _flipUIFrame; - bool _isEarlyGame; + bool _newDay; bool _buttonsLoaded; Common::String _interfaceText; int _hiliteChar; @@ -116,7 +116,7 @@ private: void drawViewBackground(int bgType); - void addCharacterToRoster(); + void moveCharacterToRoster(); void animate3d(); @@ -130,7 +130,7 @@ private: void moveMonsters(); - void setIconButtons(); + void setMainButtons(); public: Interface(XeenEngine *vm); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 52dbc839a0..e2050bdefb 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -536,8 +536,8 @@ void MazeDifficulties::synchronize(Common::SeekableReadStream &s) { MazeData::MazeData() { for (int y = 0; y < MAP_HEIGHT; ++y) { - Common::fill(&_wallData[y][0], &_wallData[y][MAP_WIDTH], 0); - Common::fill(&_cellFlag[y][0], &_cellFlag[y][MAP_WIDTH], 0); + for (int x = 0; x < MAP_WIDTH; ++x) + _wallData[y][x]._data = 0; Common::fill(&_seenTiles[y][0], &_seenTiles[y][MAP_WIDTH], 0); Common::fill(&_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH], 0); _wallTypes[y] = 0; @@ -554,11 +554,14 @@ MazeData::MazeData() { void MazeData::synchronize(Common::SeekableReadStream &s) { for (int y = 0; y < MAP_HEIGHT; ++y) { for (int x = 0; x < MAP_WIDTH; ++x) - _wallData[y][x] = s.readUint16LE(); + _wallData[y][x]._data = s.readUint16LE(); } for (int y = 0; y < MAP_HEIGHT; ++y) { - for (int x = 0; x < MAP_WIDTH; ++x) - _cellFlag[y][x] = s.readByte(); + for (int x = 0; x < MAP_WIDTH; ++x) { + byte b = s.readByte(); + _cells[y][x]._surfaceId = b & 7; + _cells[y][x]._flags = b & 0xF8; + } } _mazeNumber = s.readUint16LE(); @@ -594,10 +597,10 @@ void MazeData::setAllTilesStepped() { Common::fill(&_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH], true); } -void MazeData::clearCellBits() { +void MazeData::clearCellSurfaces() { for (int y = 0; y < MAP_HEIGHT; ++y) { for (int x = 0; x < MAP_WIDTH; ++x) - _cellFlag[y][x] &= 0xF8; + _cells[y][x]._surfaceId = 0; } } @@ -763,6 +766,15 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { _sideMon = 0; _isOutdoors = false; _stepped = false; + _mazeDataIndex = 0; + _currentSteppedOn = false; + _currentSurfaceId = 0; + _currentIsGrate = false; + _currentCantRest = false; + _currentIsDrain = false; + _currentIsEvent = false; + _currentIsObject = false; + _currentMonsterFlags = 0; } void Map::load(int mapId) { @@ -851,7 +863,7 @@ void Map::load(int mapId) { mazeData->setAllTilesStepped(); if (!isDarkCc && _vm->_party._gameFlags[25] && (mapId == 42 || mapId == 43 || mapId == 4)) { - mazeData->clearCellBits(); + mazeData->clearCellSurfaces(); } _isOutdoors = (mazeData->_mazeFlags2 & FLAG_IS_OUTDOORS) != 0; @@ -948,4 +960,128 @@ void Map::load(int mapId) { } } +int Map::mazeLookup(const Common::Point &pt, int directionLayerIndex) { + Common::Point pos = pt; + int mapId = _vm->_party._mazeId; + + if (pt.x < -16 || pt.y < -16 || pt.x >= 32 || pt.y >= 32) + error("Invalid coordinate"); + + // Find the correct maze data out of the set to use + _mazeDataIndex = 0; + while (_mazeData[_mazeDataIndex]._mazeId != _vm->_party._mazeId) + ++_mazeDataIndex; + + // Handle map changing to the north or south as necessary + if (pos.y & 16) { + if (pos.y >= 0) { + pos.y -= 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._north; + } else { + pos.y += 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._south; + } + + if (mapId) { + // Move to the correct map to north/south + _mazeDataIndex = 0; + while (_mazeData[_mazeDataIndex]._mazeId != mapId) + ++_mazeDataIndex; + } else { + // No map, so reached outside indoor area or outer space outdoors + _currentSteppedOn = true; + return _isOutdoors ? SURFTYPE_SPACE : 0x8888; + } + } + + // Handle map changing to the east or west as necessary + if (pos.x & 16) { + if (pos.x >= 0) { + pos.x -= 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._east; + } else { + pos.x += 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._west; + } + + if (mapId) { + _mazeDataIndex = 0; + while (_mazeData[_mazeDataIndex]._mazeId != mapId) + ++_mazeDataIndex; + } + } + + if (mapId) { + if (_isOutdoors) { + _currentSurfaceId = _mazeData[_mazeDataIndex]._wallData[pos.y][pos.x]._outdoors._surfaceId; + } else { + _currentSurfaceId = _mazeData[_mazeDataIndex]._cells[pos.y][pos.x]._surfaceId; + } + + if (_currentSurfaceId == SURFTYPE_SPACE || _currentSurfaceId == SURFTYPE_SKY) { + _currentSteppedOn = true; + } else { + _currentSteppedOn = _mazeData[_mazeDataIndex]._steppedOnTiles[pos.y][pos.x]; + } + + return (_mazeData[_mazeDataIndex]._wallData[pos.y][pos.x]._data >> (directionLayerIndex * 4)) & 0xF; + + } else { + _currentSteppedOn = _isOutdoors; + return _isOutdoors ? SURFTYPE_SPACE : 0x8888; + } +} + +void Map::cellFlagLookup(const Common::Point &pt) { + Common::Point pos = pt; + int mapId = _vm->_party._mazeId; + _mazeDataIndex = 0; + while (_mazeData[_mazeDataIndex]._mazeId != mapId) + ++_mazeDataIndex; + + // Handle map changing to the north or south as necessary + if (pos.y & 16) { + if (pos.y >= 0) { + pos.y -= 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._north; + } else { + pos.y += 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._south; + } + + _mazeDataIndex = 0; + while (_mazeData[_mazeDataIndex]._mazeId != mapId) + ++_mazeDataIndex; + } + + // Handle map changing to the east or west as necessary + if (pos.x & 16) { + if (pos.x >= 0) { + pos.x -= 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._east; + } else { + pos.x += 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._west; + } + + _mazeDataIndex = 0; + while (_mazeData[_mazeDataIndex]._mazeId != mapId) + ++_mazeDataIndex; + } + + // Get the cell flags + const MazeCell &cell = _mazeData[_mazeDataIndex]._cells[pos.y][pos.x]; + _currentIsGrate = cell._flags & OUTFLAG_GRATE; + _currentCantRest = cell._flags & FLAG_WATER; + _currentIsDrain = cell._flags & OUTFLAG_DRAIN; + _currentIsEvent = cell._flags & FLAG_AUTOEXECUTE_EVENT; + _currentIsObject = cell._flags & OUTFLAG_OBJECT_EXISTS; + _currentMonsterFlags = cell._flags & 7; +} + +void Map::setCellSurfaceFlags(const Common::Point &pt, int bits) { + mazeLookup(pt, 0); + _mazeData[0]._cells[pt.y][pt.x]._surfaceId |= bits; +} + } // End of namespace Xeen diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 30c2c643df..3a1073eda2 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -36,7 +36,7 @@ namespace Xeen { class XeenEngine; -enum DamageType { +enum DamageType { DT_PHYSICAL = 0, DT_1 = 1, DT_FIRE = 2, DT_ELECTRICAL = 3, DT_COLD = 4, DT_POISON = 5, DT_ENERGY = 6, DT_SLEEP = 7, DT_FINGEROFDEATH = 8, DT_HOLYWORD = 9, DT_MASS_DISTORTION = 10, @@ -156,11 +156,42 @@ enum MazeFlags { enum MazeFlags2 { FLAG_IS_OUTDOORS = 0x8000, FLAG_IS_DARK = 0x4000 }; +enum SurfaceType { + SURFTYPE_DEFAULT = 0, SURFTYPE_DIRT = 1, SURFTYPE_GRASS = 2, + SURFTYPE_SNOW = 3, SURFTYPE_SWAMP = 4, SURFTYPE_LAVA = 5, + SURFTYPE_DESERT = 6, SURFTYPE_ROAD = 7, SURFTYPE_WATER = 8, + SURFTYPE_TFLR = 9, SURFTYPE_SKY = 10, SURFTYPE_CROAD = 11, + SURFTYPE_SEWER = 12, SURFTYPE_CLOUD = 13, SURFTYPE_SCORCH = 14, + SURFTYPE_SPACE = 15 +}; + +union MazeWallLayers { + struct MazeWallIndoors { + int _wallNorth : 4; + int _wallEast : 4; + int _wallSouth : 4; + int _wallWest : 4; + } _indoors; + struct MazeWallOutdoors { + SurfaceType _surfaceId : 4; + int _iMiddle : 4; + int _iTop : 4; + int _iOverlay : 4; + } _outdoors; + uint16 _data; +}; + +struct MazeCell { + int _flags; + int _surfaceId; + MazeCell() : _flags(0), _surfaceId(0) {} +}; + class MazeData { public: // Resource fields - int _wallData[MAP_HEIGHT][MAP_WIDTH]; - int _cellFlag[MAP_HEIGHT][MAP_WIDTH]; + MazeWallLayers _wallData[MAP_HEIGHT][MAP_WIDTH]; + MazeCell _cells[MAP_HEIGHT][MAP_WIDTH]; int _mazeNumber; SurroundingMazes _surroundingMazes; int _mazeFlags; @@ -185,7 +216,7 @@ public: void setAllTilesStepped(); - void clearCellBits(); + void clearCellSurfaces(); }; class MobStruct { @@ -293,13 +324,28 @@ private: int _sideObj; int _sideMon; bool _stepped; + int _mazeDataIndex; + bool _currentSteppedOn; + int _currentSurfaceId; + + void cellFlagLookup(const Common::Point &pt); public: bool _isOutdoors; MonsterObjectData _mobData; + bool _currentIsGrate; + bool _currentCantRest; + bool _currentIsDrain; + bool _currentIsEvent; + bool _currentIsObject; + int _currentMonsterFlags; public: Map(XeenEngine *vm); void load(int mapId); + + int mazeLookup(const Common::Point &pt, int directionLayerIndex); + + void setCellSurfaceFlags(const Common::Point &pt, int bits); }; } // End of namespace Xeen diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index ec25f4a71c..ad6d2145de 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -135,7 +135,7 @@ void PlayerStruct::synchronize(Common::Serializer &s) { s.syncAsByte(_currentCombatSpell); } -Condition PlayerStruct::findCondition() const { +Condition PlayerStruct::worstCondition() const { for (int cond = ERADICATED; cond >= CURSED; --cond) { if (_conditions[cond]) return (Condition)cond; @@ -144,7 +144,7 @@ Condition PlayerStruct::findCondition() const { return NO_CONDITION; } -int PlayerStruct::getYear(int partyYear, bool ignoreTemp) { +int PlayerStruct::getAge(int partyYear, bool ignoreTemp) { int year = MIN(partyYear - _ybDay, 254); return ignoreTemp ? year : year + _tempAge; diff --git a/engines/xeen/party.h b/engines/xeen/party.h index b415707344..f1220c82e9 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -126,9 +126,9 @@ public: PlayerStruct(); void synchronize(Common::Serializer &s); - Condition findCondition() const; + Condition worstCondition() const; - int getYear(int partyYear, bool ignoreTemp); + int getAge(int partyYear, bool ignoreTemp); int getMaxHp(); }; diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index f375b985f8..da6548b07d 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -39,7 +39,7 @@ public: void startMusic(int v1); - void playMusic(const File &f) {} + void playSong(const File &f) {} void playSample(const Common::SeekableReadStream *stream, int v2) {} }; diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index c2abdd9e9f..9cc51e1765 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -46,7 +46,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _sound = nullptr; _eventData = nullptr; _loadDarkSide = 1; - _spotDoorsAllowed = false; + _thinWall = false; _dangerSenseAllowed = false; _face1State = 0; _face2State = 0; diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 44deaee43c..efeacf0ae1 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -138,7 +138,7 @@ public: Roster _roster; Party _party; int _loadDarkSide; - bool _spotDoorsAllowed; + bool _thinWall; bool _dangerSenseAllowed; int _face1State; int _face2State; -- cgit v1.2.3 From 0b5f79afb7dbf0d2bcf3cb14747f93f348b1aaa5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 11 Jan 2015 10:43:02 -0500 Subject: XEEN: Added loading of event data for maps --- engines/xeen/map.cpp | 29 +++++++++++- engines/xeen/map.h | 4 ++ engines/xeen/module.mk | 1 + engines/xeen/party.h | 4 +- engines/xeen/scripts.cpp | 54 +++++++++++++++++++++ engines/xeen/scripts.h | 119 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 engines/xeen/scripts.cpp create mode 100644 engines/xeen/scripts.h (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index e2050bdefb..d07ca2d363 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -842,12 +842,15 @@ void Map::load(int mapId) { } } + // Load any events for the new map + loadEvents(mapId); + + // Iterate through loading the given maze as well as the two successive + // mazes in each of the four cardinal directions bool isDarkCc = _vm->getGameID() == GType_DarkSide; MazeData *mazeData = &_mazeData[0]; bool textLoaded = false; - // Iterate through loading the given maze as well as the two successive - // mazes in each of the four cardinal directions for (int idx = 0; idx < 9; ++idx, ++mazeData) { mazeData->_mazeId = mapId; @@ -1032,6 +1035,28 @@ int Map::mazeLookup(const Common::Point &pt, int directionLayerIndex) { } } +/** + * Load the events for a new map + */ +void Map::loadEvents(int mapId) { + // Load events + Common::String filename = Common::String::format("maze%c%03d.evt", + (mapId >= 100) ? 'x' : '0', mapId); + File fEvents(filename); + _events.synchronize(fEvents); + fEvents.close(); + + // Load text data + filename = Common::String::format("aaze%c%03d.txt", + (mapId >= 100) ? 'x' : '0', mapId); + File fText(filename); + _events._text.resize(fText.size()); + fText.read(&_events._text[0], fText.size()); + + _events.synchronize(fText); + fText.close(); +} + void Map::cellFlagLookup(const Common::Point &pt) { Common::Point pos = pt; int mapId = _vm->_party._mazeId; diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 3a1073eda2..bc1b0245b9 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -27,6 +27,7 @@ #include "common/array.h" #include "common/rect.h" #include "xeen/party.h" +#include "xeen/scripts.h" #include "xeen/sprites.h" namespace Xeen { @@ -328,10 +329,13 @@ private: bool _currentSteppedOn; int _currentSurfaceId; + void loadEvents(int mapId); + void cellFlagLookup(const Common::Point &pt); public: bool _isOutdoors; MonsterObjectData _mobData; + MazeEvents _events; bool _currentIsGrate; bool _currentCantRest; bool _currentIsDrain; diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 5cbb1bb064..076a31a916 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -20,6 +20,7 @@ MODULE_OBJS := \ resources.o \ saves.o \ screen.o \ + scripts.o \ sound.o \ sprites.o \ xeen.o \ diff --git a/engines/xeen/party.h b/engines/xeen/party.h index f1220c82e9..d8fe2ab79d 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -31,7 +31,9 @@ namespace Xeen { -enum Direction { DIR_NORTH = 0, DIR_EAST = 1, DIR_SOUTH = 2, DIR_WEST = 3 }; +enum Direction { + DIR_NORTH = 0, DIR_EAST = 1, DIR_SOUTH = 2, DIR_WEST = 3, DIR_ALL = 4 +}; enum Difficulty { ADVENTURER = 0, WARRIOR = 1 }; diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp new file mode 100644 index 0000000000..ee804317ec --- /dev/null +++ b/engines/xeen/scripts.cpp @@ -0,0 +1,54 @@ +/* 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 "xeen/scripts.h" + +namespace Xeen { + +MazeEvent::MazeEvent() : _direction(DIR_ALL), _line(-1), _opcode(OP_None) { +} + +void MazeEvent::synchronize(Common::SeekableReadStream &s) { + int len = s.readByte(); + _position.x = s.readByte(); + _position.y = s.readByte(); + _direction = (Direction)s.readByte(); + _line = s.readByte(); + _opcode = (Opcode)s.readByte(); + + for (int i = 0; i < (len - 5); ++i) + _parameters.push_back(s.readByte()); +} + +/*------------------------------------------------------------------------*/ + +void MazeEvents::synchronize(Common::SeekableReadStream &s) { + MazeEvent e; + + clear(); + while (!s.eos()) { + e.synchronize(s); + push_back(e); + } +} + +} // End of namespace Xeen diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h new file mode 100644 index 0000000000..1ab08faa7e --- /dev/null +++ b/engines/xeen/scripts.h @@ -0,0 +1,119 @@ +/* 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 XEEN_SCRIPTS_H +#define XEEN_SCRIPTS_H + +#include "common/scummsys.h" +#include "common/system.h" +#include "common/stream.h" +#include "xeen/party.h" + +namespace Xeen { + +enum Opcode { + OP_None = 0x00, + OP_Display0x01 = 0x01, + OP_DoorTextSml = 0x02, + OP_DoorTextLrg = 0x03, + OP_SignText = 0x04, + OP_NPC = 0x05, + OP_PlayFX = 0x06, + OP_TeleportAndExit = 0x07, + OP_If_1 = 0x08, + OP_If_2 = 0x09, + OP_If3 = 0x0A, + OP_MoveObj = 0x0B, + OP_TakeOrGive = 0x0C, + OP_NoAction = 0x0D, + OP_Remove = 0x0E, + OP_SetChar = 0x0F, + OP_Spawn = 0x10, + OP_DoTownEvent = 0x11, + OP_Exit = 0x12, + OP_AfterMap = 0x13, + OP_GiveExtended = 0x14, + OP_ConfirmWord = 0x15, + OP_Damage = 0x16, + OP_JumpRnd = 0x17, + OP_AfterEvent = 0x18, + OP_CallEvent = 0x19, + OP_Return = 0x1A, + OP_SetVar = 0x1B, + OP_TakeOrGive_2 = 0x1C, + OP_TakeOrGive_3 = 0x1D, + OP_CutsceneEndClouds = 0x1E, + OP_TeleportAndContinue = 0x1F, + OP_WhoWill = 0x20, + OP_RndDamage = 0x21, + OP_MoveWallObj = 0x22, + OP_AlterCellFlag= 0x23, + OP_AlterHed = 0x24, + OP_DisplayStat = 0x25, + OP_TakeOrGive_4 = 0x26, + OP_SeatTextSml = 0x27, + OP_PlayEventVoc = 0x28, + OP_DisplayBottom = 0x29, + OP_IfMapFlag = 0x2A, + OP_SelRndChar = 0x2B, + OP_GiveEnchanted= 0x2C, + OP_ItemType = 0x2D, + OP_MakeNothingHere = 0x2E, + OP_NoAction_2 = 0x2F, + OP_ChooseNumeric= 0x30, + OP_DisplayBottomTwoLines = 0x31, + OP_DisplayLarge = 0x32, + OP_ExchObj = 0x33, + OP_FallToMap = 0x34, + OP_DisplayMain = 0x35, + OP_Goto = 0x36, + OP_ConfirmWord_2= 0x37, + OP_GotoRandom = 0x38, + OP_CutsceneEndDarkside = 0x39, + OP_CutsceneEdWorld = 0x3A, + OP_FlipWorld = 0x3B, + OP_PlayCD = 0x3C +}; + +class MazeEvent { +public: + Common::Point _position; + int _direction; + int _line; + Opcode _opcode; + Common::Array<byte> _parameters; +public: + MazeEvent(); + + void synchronize(Common::SeekableReadStream &s); +}; + +class MazeEvents : public Common::Array<MazeEvent> { +public: + Common::Array<byte> _text; +public: + void synchronize(Common::SeekableReadStream &s); +}; + +} // End of namespace Xeen + +#endif /* XEEN_SCRIPTS_H */ -- cgit v1.2.3 From 3b1edcdf36fc7a207a70cb28e7dcf7879ea9b7e5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 11 Jan 2015 14:21:57 -0500 Subject: XEEN: Implemented code for 'saving' resources to the loaded savefile --- engines/xeen/files.cpp | 2 +- engines/xeen/files.h | 15 +++++++++++++-- engines/xeen/map.cpp | 21 +++++++++++++++++---- engines/xeen/map.h | 2 ++ engines/xeen/saves.cpp | 25 +++++++++++++++++++++++++ engines/xeen/saves.h | 16 ++++++++++++++++ engines/xeen/scripts.cpp | 40 +++++++++++++++++++++++++--------------- engines/xeen/scripts.h | 7 ++++--- 8 files changed, 103 insertions(+), 25 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index 79387f2e24..8ab1f35fcb 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -32,7 +32,7 @@ namespace Xeen { /** * Hash a given filename to produce the Id that represents it */ -uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) const { +uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) { if (resourceName.empty()) return 0xffff; diff --git a/engines/xeen/files.h b/engines/xeen/files.h index 343aea1e74..7c0817a850 100644 --- a/engines/xeen/files.h +++ b/engines/xeen/files.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/array.h" #include "common/file.h" +#include "common/serializer.h" #include "graphics/surface.h" #include "xeen/xsurface.h" @@ -61,6 +62,16 @@ public: void openFile(const Common::String &filename, Common::Archive &archive); }; +class XeenSerializer : public Common::Serializer { +private: + Common::SeekableReadStream *_in; +public: + XeenSerializer(Common::SeekableReadStream *in, Common::WriteStream *out) : + Common::Serializer(in, out), _in(in) {} + + bool finished() const { return _in != nullptr && _in->pos() >= _in->size(); } +}; + /** * Details of a single entry in a CC file index */ @@ -79,14 +90,14 @@ struct CCEntry { * Base Xeen CC file implementation */ class BaseCCArchive : public Common::Archive { -private: - uint16 convertNameToId(const Common::String &resourceName) const; protected: Common::Array<CCEntry> _index; void loadIndex(Common::SeekableReadStream *stream); virtual bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const; +public: + static uint16 convertNameToId(const Common::String &resourceName); public: BaseCCArchive() {} diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index d07ca2d363..d65e09d5d7 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1042,8 +1042,9 @@ void Map::loadEvents(int mapId) { // Load events Common::String filename = Common::String::format("maze%c%03d.evt", (mapId >= 100) ? 'x' : '0', mapId); - File fEvents(filename); - _events.synchronize(fEvents); + File fEvents(filename, *_vm->_saves); + XeenSerializer sEvents(&fEvents, nullptr); + _events.synchronize(sEvents); fEvents.close(); // Load text data @@ -1052,11 +1053,23 @@ void Map::loadEvents(int mapId) { File fText(filename); _events._text.resize(fText.size()); fText.read(&_events._text[0], fText.size()); - - _events.synchronize(fText); fText.close(); } +void Map::saveMaze() { + int mazeNum = _mazeData[0]._mazeNumber; + if (!mazeNum || (mazeNum == 85 && !_vm->_files->_isDarkCc)) + return; + + // Save the event data + Common::String filename = Common::String::format("maze%c%03d.evt", + (mazeNum >= 100) ? 'x' : '0', mazeNum); + OutFile fEvents(_vm, filename); + XeenSerializer sEvents(nullptr, &fEvents); + _events.synchronize(sEvents); + fEvents.finalize(); +} + void Map::cellFlagLookup(const Common::Point &pt) { Common::Point pos = pt; int mapId = _vm->_party._mazeId; diff --git a/engines/xeen/map.h b/engines/xeen/map.h index bc1b0245b9..c23b214736 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -350,6 +350,8 @@ public: int mazeLookup(const Common::Point &pt, int directionLayerIndex); void setCellSurfaceFlags(const Common::Point &pt, int bits); + + void saveMaze(); }; } // End of namespace Xeen diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index e6bfa80e09..c2b15106eb 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -29,6 +29,22 @@ namespace Xeen { +OutFile::OutFile(XeenEngine *vm, const Common::String filename) : + _vm(vm), _filename(filename) { +} + +void OutFile::finalize() { + uint16 id = BaseCCArchive::convertNameToId(_filename); + + if (!_vm->_saves->_newData.contains(id)) + _vm->_saves->_newData[id] = Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES); + + Common::MemoryWriteStreamDynamic &out = _vm->_saves->_newData[id]; + out.write(getData(), size()); +} + +/*------------------------------------------------------------------------*/ + SavesManager::SavesManager(XeenEngine *vm, Party &party, Roster &roster) : BaseCCArchive(), _vm(vm), _party(party), _roster(roster) { SearchMan.add("saves", this, 0, false); @@ -67,6 +83,15 @@ void SavesManager::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP) Common::SeekableReadStream *SavesManager::createReadStreamForMember(const Common::String &name) const { CCEntry ccEntry; + // If the given resource has already been perviously "written" to the + // save manager, then return that new resource + uint16 id = BaseCCArchive::convertNameToId(name); + if (_newData.contains(id)) { + Common::MemoryWriteStreamDynamic stream = _newData[id]; + return new Common::MemoryReadStream(stream.getData(), stream.size()); + } + + // Retrieve the resource from the loaded savefile if (getHeaderEntry(name, ccEntry)) { // Open the correct CC entry return new Common::MemoryReadStream(_data + ccEntry._offset, ccEntry._size); diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h index ed4b80b29d..6b73625c61 100644 --- a/engines/xeen/saves.h +++ b/engines/xeen/saves.h @@ -24,6 +24,7 @@ #define XEEN_SAVES_H #include "common/scummsys.h" +#include "common/memstream.h" #include "common/savefile.h" #include "graphics/surface.h" #include "xeen/party.h" @@ -40,12 +41,27 @@ struct XeenSavegameHeader { int _totalFrames; }; +class XeenEngine; +class SavesManager; + +class OutFile : public Common::MemoryWriteStreamDynamic { +private: + XeenEngine *_vm; + Common::String _filename; +public: + OutFile(XeenEngine *vm, const Common::String filename); + + void finalize(); +}; + class SavesManager: public BaseCCArchive { + friend class OutFile; private: XeenEngine *_vm; Party &_party; Roster &_roster; byte *_data; + Common::HashMap<uint16, Common::MemoryWriteStreamDynamic > _newData; void load(Common::SeekableReadStream *stream); public: diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index ee804317ec..0a864aa2cb 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -27,27 +27,37 @@ namespace Xeen { MazeEvent::MazeEvent() : _direction(DIR_ALL), _line(-1), _opcode(OP_None) { } -void MazeEvent::synchronize(Common::SeekableReadStream &s) { - int len = s.readByte(); - _position.x = s.readByte(); - _position.y = s.readByte(); - _direction = (Direction)s.readByte(); - _line = s.readByte(); - _opcode = (Opcode)s.readByte(); - - for (int i = 0; i < (len - 5); ++i) - _parameters.push_back(s.readByte()); +void MazeEvent::synchronize(Common::Serializer &s) { + int len = 5 + _parameters.size(); + s.syncAsByte(len); + + s.syncAsByte(_position.x); + s.syncAsByte(_position.y); + s.syncAsByte(_direction); + s.syncAsByte(_line); + s.syncAsByte(_opcode); + + len -= 5; + if (s.isLoading()) + _parameters.resize(len); + for (int i = 0; i < len; ++i) + s.syncAsByte(_parameters[i]); } /*------------------------------------------------------------------------*/ -void MazeEvents::synchronize(Common::SeekableReadStream &s) { +void MazeEvents::synchronize(XeenSerializer &s) { MazeEvent e; - clear(); - while (!s.eos()) { - e.synchronize(s); - push_back(e); + if (s.isLoading()) { + clear(); + while (!s.finished()) { + e.synchronize(s); + push_back(e); + } + } else { + for (uint i = 0; i < size(); ++i) + (*this).operator[](i).synchronize(s); } } diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 1ab08faa7e..727d37f681 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -25,7 +25,8 @@ #include "common/scummsys.h" #include "common/system.h" -#include "common/stream.h" +#include "common/serializer.h" +#include "xeen/files.h" #include "xeen/party.h" namespace Xeen { @@ -104,14 +105,14 @@ public: public: MazeEvent(); - void synchronize(Common::SeekableReadStream &s); + void synchronize(Common::Serializer &s); }; class MazeEvents : public Common::Array<MazeEvent> { public: Common::Array<byte> _text; public: - void synchronize(Common::SeekableReadStream &s); + void synchronize(XeenSerializer &s); }; } // End of namespace Xeen -- cgit v1.2.3 From edccbe63f24e26944dcd7cd3da59b6842cb36b46 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 11 Jan 2015 16:01:10 -0500 Subject: XEEN: Added saving of maze monster/object data --- engines/xeen/files.h | 15 ++++ engines/xeen/interface.cpp | 1 - engines/xeen/map.cpp | 201 +++++++++++++++++++++++++++++---------------- engines/xeen/map.h | 5 +- 4 files changed, 147 insertions(+), 75 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/files.h b/engines/xeen/files.h index 7c0817a850..a8343c1653 100644 --- a/engines/xeen/files.h +++ b/engines/xeen/files.h @@ -34,6 +34,19 @@ namespace Xeen { class XeenEngine; +#define SYNC_AS(SUFFIX,STREAM,TYPE,SIZE) \ + template<typename T> \ + void syncAs ## SUFFIX(T &val, Version minVersion = 0, Version maxVersion = kLastVersion) { \ + if (_version < minVersion || _version > maxVersion) \ + return; \ + if (_loadStream) \ + val = static_cast<TYPE>(_loadStream->read ## STREAM()); \ + else { \ + TYPE tmp = (TYPE)val; \ + _saveStream->write ## STREAM(tmp); \ + } \ + _bytesSynced += SIZE; \ + } /* * Main resource manager */ @@ -69,6 +82,8 @@ public: XeenSerializer(Common::SeekableReadStream *in, Common::WriteStream *out) : Common::Serializer(in, out), _in(in) {} + SYNC_AS(Sint8, Byte, int8, 1) + bool finished() const { return _in != nullptr && _in->pos() >= _in->size(); } }; diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index f952425d05..c2c907b898 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -883,7 +883,6 @@ void Interface::setIndoorsMonsters() { void Interface::setIndoorObjects() { Common::Point mazePos = _vm->_party._mazePosition; _objNumber = 0; - int objIndx = 0; const int8 *posOffset = &SCREEN_POSITIONING[_vm->_party._mazeDirection * 48]; Common::Point pt; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index d65e09d5d7..c70b0cfe6d 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -611,11 +611,11 @@ MobStruct::MobStruct() { _direction = DIR_NORTH; } -bool MobStruct::synchronize(Common::SeekableReadStream &s) { - _pos.x = (int8)s.readByte(); - _pos.y = (int8)s.readByte(); - _id = s.readByte(); - _direction = (Direction)s.readByte(); +bool MobStruct::synchronize(XeenSerializer &s) { + s.syncAsSint8(_pos.x); + s.syncAsSint8(_pos.y); + s.syncAsByte(_id); + s.syncAsByte(_direction); return _id != 0xff || _pos.x != -1 || _pos.y != -1; } @@ -658,85 +658,134 @@ MazeWallItem::MazeWallItem() { MonsterObjectData::MonsterObjectData(XeenEngine *vm): _vm(vm) { } -void MonsterObjectData::synchronize(Common::SeekableReadStream &s, - bool isOutdoors, MonsterData monsterData) { - _objectSprites.clear(); - _monsterSprites.clear(); - _monsterAttackSprites.clear(); - _wallItemSprites.clear(); - _objects.clear(); - _monsters.clear(); - _wallItems.clear(); - +void MonsterObjectData::synchronize(XeenSerializer &s, MonsterData monsterData) { Common::Array<MobStruct> mobStructs; + MobStruct mobStruct; byte b; - for (int i = 0; i < 16; ++i) { - if ((b = s.readByte()) != 0xff) + if (s.isLoading()) { + _objectSprites.clear(); + _monsterSprites.clear(); + _monsterAttackSprites.clear(); + _wallItemSprites.clear(); + _objects.clear(); + _monsters.clear(); + _wallItems.clear(); + } + + for (uint i = 0; i < 16; ++i) { + b = (i >= _objectSprites.size()) ? 0xff : _objectSprites[i]._spriteId; + s.syncAsByte(b); + if (b != 0xff) _objectSprites.push_back(SpriteResourceEntry(b)); } - for (int i = 0; i < 16; ++i) { - if ((b = s.readByte()) != 0xff) + for (uint i = 0; i < 16; ++i) { + b = (i >= _monsterSprites.size()) ? 0xff : _monsterSprites[i]._spriteId; + s.syncAsByte(b); + if (b != 0xff) _monsterSprites.push_back(SpriteResourceEntry(b)); } - for (int i = 0; i < 16; ++i) { - if ((b = s.readByte()) != 0xff) + for (uint i = 0; i < 16; ++i) { + b = (i >= _wallItemSprites.size()) ? 0xff : _wallItemSprites[i]._spriteId; + s.syncAsByte(b); + if (b != 0xff) _wallItemSprites.push_back(SpriteResourceEntry(b)); } - // Merge together object data - MobStruct mobStruct; - mobStruct.synchronize(s); - do { - MazeObject obj; - obj._position = mobStruct._pos; - obj._id = mobStruct._id; - obj._direction = mobStruct._direction; - obj._frame = 100; - obj._spriteId = _objectSprites[obj._id]._spriteId; - obj._sprites = &_objectSprites[obj._id]._sprites; - - _objects.push_back(obj); + if (s.isSaving()) { + // Save objects + for (uint i = 0; i < _objects.size(); ++i) { + mobStruct._pos = _objects[i]._position; + mobStruct._id = _objects[i]._id; + mobStruct._direction = _objects[i]._direction; + mobStruct.synchronize(s); + } + mobStruct._pos.x = mobStruct._pos.y = -1; + mobStruct._id = 0xff; mobStruct.synchronize(s); - } while (mobStruct._id != 255 || mobStruct._pos.x != -1); - - // Merge together monster data - mobStruct.synchronize(s); - do { - MazeMonster mon; - mon._position = mobStruct._pos; - mon._id = mobStruct._id; - mon._spriteId = _monsterSprites[mon._id]._spriteId; - mon._sprites = &_monsterSprites[mon._id]._sprites; - mon._attackSprites = &_monsterSprites[mon._id]._attackSprites; - - MonsterStruct &md = monsterData[mon._spriteId]; - mon._hp = md._hp; - mon._frame = _vm->getRandomNumber(7); - mon._effect1 = mon._effect2 = md._animationEffect; - if (md._animationEffect) - mon._effect3 = _vm->getRandomNumber(7); - - _monsters.push_back(mon); + + // Save monsters + for (uint i = 0; i < _monsters.size(); ++i) { + mobStruct._pos = _monsters[i]._position; + mobStruct._id = _monsters[i]._id; + mobStruct._direction = DIR_NORTH; + mobStruct.synchronize(s); + } + mobStruct._pos.x = mobStruct._pos.y = -1; + mobStruct._id = 0xff; mobStruct.synchronize(s); - } while (mobStruct._id != 255 || mobStruct._pos.x != -1); - - // Merge together wall item data - mobStruct.synchronize(s); - do { - if (mobStruct._id < (int)_wallItemSprites.size()) { - MazeWallItem wi; - wi._position = mobStruct._pos; - wi._id = mobStruct._id; - wi._direction = mobStruct._direction; - wi._spriteId = _wallItemSprites[wi._id]._spriteId; - wi._sprites = &_wallItemSprites[wi._id]._sprites; - - _wallItems.push_back(wi); + + // Save wall items + if (_wallItems.size() == 0) { + MobStruct nullStruct; + nullStruct.synchronize(s); + } else { + for (uint i = 0; i < _wallItems.size(); ++i) { + mobStruct._pos = _wallItems[i]._position; + mobStruct._id = _wallItems[i]._id; + mobStruct._direction = _wallItems[i]._direction; + mobStruct.synchronize(s); + } } + mobStruct._pos.x = mobStruct._pos.y = -1; + mobStruct._id = 0xff; + mobStruct.synchronize(s); + } else { + // Load monster/obbject data and merge together with sprite Ids + // Merge together object data + mobStruct.synchronize(s); + do { + MazeObject obj; + obj._position = mobStruct._pos; + obj._id = mobStruct._id; + obj._direction = mobStruct._direction; + obj._frame = 100; + obj._spriteId = _objectSprites[obj._id]._spriteId; + obj._sprites = &_objectSprites[obj._id]._sprites; + + _objects.push_back(obj); + mobStruct.synchronize(s); + } while (mobStruct._id != 255 || mobStruct._pos.x != -1); + + // Merge together monster data mobStruct.synchronize(s); - } while (mobStruct._id != 255 || mobStruct._pos.x != -1); + do { + MazeMonster mon; + mon._position = mobStruct._pos; + mon._id = mobStruct._id; + mon._spriteId = _monsterSprites[mon._id]._spriteId; + mon._sprites = &_monsterSprites[mon._id]._sprites; + mon._attackSprites = &_monsterSprites[mon._id]._attackSprites; + + MonsterStruct &md = monsterData[mon._spriteId]; + mon._hp = md._hp; + mon._frame = _vm->getRandomNumber(7); + mon._effect1 = mon._effect2 = md._animationEffect; + if (md._animationEffect) + mon._effect3 = _vm->getRandomNumber(7); + + _monsters.push_back(mon); + mobStruct.synchronize(s); + } while (mobStruct._id != 255 || mobStruct._pos.x != -1); + + // Merge together wall item data + mobStruct.synchronize(s); + do { + if (mobStruct._id < (int)_wallItemSprites.size()) { + MazeWallItem wi; + wi._position = mobStruct._pos; + wi._id = mobStruct._id; + wi._direction = mobStruct._direction; + wi._spriteId = _wallItemSprites[wi._id]._spriteId; + wi._sprites = &_wallItemSprites[wi._id]._sprites; + + _wallItems.push_back(wi); + } + + mobStruct.synchronize(s); + } while (mobStruct._id != 255 || mobStruct._pos.x != -1); + } } /*------------------------------------------------------------------------*/ @@ -888,7 +937,8 @@ void Map::load(int mapId) { Common::String mobName = Common::String::format("maze%c%03d.mob", (mapId >= 100) ? 'x' : '0', mapId); File mobFile(mobName); - _mobData.synchronize(mobFile, _isOutdoors, _monsterData); + XeenSerializer sMob(&mobFile, nullptr); + _mobData.synchronize(sMob, _monsterData); mobFile.close(); Common::String headName = Common::String::format("aaze%c%03d.hed", @@ -925,7 +975,8 @@ void Map::load(int mapId) { Common::String filename = Common::String::format("maze%c%03d.mob", (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); File mobFile(filename, *_vm->_saves); - _mobData.synchronize(mobFile, _isOutdoors, _monsterData); + XeenSerializer sMob(&mobFile, nullptr); + _mobData.synchronize(sMob, _monsterData); mobFile.close(); // Load sprites for the objects @@ -1068,6 +1119,14 @@ void Map::saveMaze() { XeenSerializer sEvents(nullptr, &fEvents); _events.synchronize(sEvents); fEvents.finalize(); + + // Save the maze MOB file + filename = Common::String::format("maze%c%03d.mob", + (mazeNum >= 100) ? 'x' : '0', mazeNum); + OutFile fMob(_vm, filename); + XeenSerializer sMob(nullptr, &fEvents); + _mobData.synchronize(sMob, _monsterData); + fEvents.finalize(); } void Map::cellFlagLookup(const Common::Point &pt) { diff --git a/engines/xeen/map.h b/engines/xeen/map.h index c23b214736..d26dffff82 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -228,7 +228,7 @@ public: public: MobStruct(); - bool synchronize(Common::SeekableReadStream &s); + bool synchronize(XeenSerializer &s); }; struct MazeObject { @@ -295,8 +295,7 @@ public: public: MonsterObjectData(XeenEngine *vm); - void synchronize(Common::SeekableReadStream &s, bool isOutdoors, - MonsterData monsterData); + void synchronize(XeenSerializer &s, MonsterData monsterData); }; class HeadData { -- cgit v1.2.3 From 4745bfe182fa0824aee2525ff196d93060c2cd0c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 11 Jan 2015 17:09:48 -0500 Subject: XEEN: Implemented setIndoorObjects --- engines/xeen/interface.cpp | 143 ++++++++++++++++++++++++++++++++++++++++----- engines/xeen/interface.h | 4 +- 2 files changed, 131 insertions(+), 16 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index c2c907b898..b003e9aedd 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -358,15 +358,16 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { _newDay = false; _buttonsLoaded = false; _hiliteChar = -1; - Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); _intrIndex1 = 0; _flipWtr = false; _flag1 = false; _flag2 = false; _tillMove = 0; _objNumber = 0; - _objectFlag2 = _objectFlag3 = _objectFlag4 = _objectFlag5 = false; - _objectFlag6 = _objectFlag7 = _objectFlag8 = false; + + Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); + Common::fill(&_wp[0], &_wp[20], 0); + Common::fill(&_wo[0], &_wo[308], 0); initDrawStructs(); } @@ -886,8 +887,6 @@ void Interface::setIndoorObjects() { const int8 *posOffset = &SCREEN_POSITIONING[_vm->_party._mazeDirection * 48]; Common::Point pt; - // TODO: Fields loading - Common::Array<MazeObject> &objects = _vm->_map->_mobData._objects; for (uint idx = 0; idx < objects.size(); ++idx) { MazeObject &mazeObject = objects[idx]; @@ -896,7 +895,8 @@ void Interface::setIndoorObjects() { int listOffset; if (_vm->_files->_isDarkCc) { listOffset = mazeObject._spriteId == 47 ? 1 : 0; - } else { + } + else { listOffset = mazeObject._spriteId == 113 ? 1 : 0; } @@ -915,7 +915,7 @@ void Interface::setIndoorObjects() { // Position 2 pt = Common::Point(mazePos.x + posOffset[7], mazePos.y + posOffset[199]); - if (pt == mazeObject._position && !_objectFlag2 && _indoorList._objects1._frame == -1) { + if (pt == mazeObject._position && !_wo[27] && _indoorList._objects1._frame == -1) { _indoorList._objects1._x = INDOOR_OBJECT_X[listOffset][1]; _indoorList._objects1._y = INDOOR_OBJECT_Y[listOffset][1]; _indoorList._objects1._frame = mazeObject._frame; @@ -923,24 +923,139 @@ void Interface::setIndoorObjects() { _indoorList._objects1._flags &= ~SPRFLAG_HORIZ_FLIPPED; if (mazeObject._flipped) _indoorList._objects1._flags |= SPRFLAG_HORIZ_FLIPPED; - _objNumber = idx; } // Position 3 pt = Common::Point(mazePos.x + posOffset[5], mazePos.y + posOffset[197]); - if (pt == mazeObject._position && !_objectFlag2 && _indoorList._objects2._frame == -1) { - _indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][1]; - _indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][1]; + if (pt == mazeObject._position && (!_wo[27] || !_wo[25]) && (!_wo[27] || !_wo[28]) && + (!_wo[23] || !_wo[25]) && (!_wo[23] || !_wo[28]) && + _indoorList._objects2._frame == -1) { + _indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][2]; + _indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][2]; _indoorList._objects2._frame = mazeObject._frame; _indoorList._objects2._sprites = mazeObject._sprites; _indoorList._objects2._flags &= ~SPRFLAG_HORIZ_FLIPPED; if (mazeObject._flipped) _indoorList._objects2._flags |= SPRFLAG_HORIZ_FLIPPED; - _objNumber = idx; } - // Position 4 onwards - // TODO: Also resolve usage of _objectFlag* flags + // Position 4 + pt = Common::Point(mazePos.x + posOffset[9], mazePos.y + posOffset[201]); + if (pt == mazeObject._position && (!_wo[27] || !_wo[26]) && (!_wo[27] || !_wo[29]) && + (!_wo[24] || !_wo[26]) && (!_wo[24] || !_wo[29]) && _indoorList._objects3._frame == -1) { + _indoorList._objects3._x = INDOOR_OBJECT_X[listOffset][3]; + _indoorList._objects3._y = INDOOR_OBJECT_Y[listOffset][3]; + _indoorList._objects3._frame = mazeObject._frame; + _indoorList._objects3._sprites = mazeObject._sprites; + _indoorList._objects3._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects3._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Position 5 + pt = Common::Point(mazePos.x + posOffset[14], mazePos.y + posOffset[206]); + if (pt == mazeObject._position && !_wo[22] && !_wo[27] && _indoorList._objects4._frame == -1) { + _indoorList._objects4._x = INDOOR_OBJECT_X[listOffset][4]; + _indoorList._objects4._y = INDOOR_OBJECT_Y[listOffset][4]; + _indoorList._objects4._frame = mazeObject._frame; + _indoorList._objects4._sprites = mazeObject._sprites; + _indoorList._objects4._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects4._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Position 6 + pt = Common::Point(mazePos.x + posOffset[12], mazePos.y + posOffset[204]); + if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[23]) && (!_wo[22] || !_wo[20]) && + (!_wo[23] || !_wo[17]) && (!_wo[20] || !_wo[17]) && _indoorList._objects5._frame == -1) { + _indoorList._objects5._x = INDOOR_OBJECT_X[listOffset][5]; + _indoorList._objects5._y = INDOOR_OBJECT_Y[listOffset][5]; + _indoorList._objects5._frame = mazeObject._frame; + _indoorList._objects5._sprites = mazeObject._sprites; + _indoorList._objects5._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects5._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Position 7 + pt = Common::Point(mazePos.x + posOffset[16], mazePos.y + posOffset[208]); + if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[24]) && (!_wo[22] || !_wo[21]) && + (!_wo[24] || !_wo[19]) && (!_wo[21] || !_wo[19]) && _indoorList._objects6._frame == -1) { + _indoorList._objects6._x = INDOOR_OBJECT_X[listOffset][6]; + _indoorList._objects6._y = INDOOR_OBJECT_Y[listOffset][6]; + _indoorList._objects6._frame = mazeObject._frame; + _indoorList._objects6._sprites = mazeObject._sprites; + _indoorList._objects6._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects6._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Position 8 + pt = Common::Point(mazePos.x + posOffset[27], mazePos.y + posOffset[219]); + if (pt == mazeObject._position && !_wo[27] && !_wo[22] && !_wo[15] && _indoorList._objects7._frame == -1) { + _indoorList._objects7._x = INDOOR_OBJECT_X[listOffset][7]; + _indoorList._objects7._y = INDOOR_OBJECT_Y[listOffset][7]; + _indoorList._objects7._frame = mazeObject._frame; + _indoorList._objects7._sprites = mazeObject._sprites; + _indoorList._objects7._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects7._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Position 9 + pt = Common::Point(mazePos.x + posOffset[25], mazePos.y + posOffset[217]); + if (pt == mazeObject._position && !_wo[27] && (!_wo[15] || !_wo[17]) && (!_wo[15] || !_wo[12]) && + (!_wo[12] || !_wo[7]) && (!_wo[17] || !_wo[7]) && _indoorList._objects5._frame == -1) { + _indoorList._objects8._x = INDOOR_OBJECT_X[listOffset][8]; + _indoorList._objects8._y = INDOOR_OBJECT_Y[listOffset][8]; + _indoorList._objects8._frame = mazeObject._frame; + _indoorList._objects8._sprites = mazeObject._sprites; + _indoorList._objects8._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects8._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Position 10 + pt = Common::Point(mazePos.x + posOffset[23], mazePos.y + posOffset[215]); + if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[20]) && (!_wo[22] || !_wo[23]) && + (!_wo[20] || !_wo[17]) && (!_wo[23] || !_wo[17]) && !_wo[12] && !_wo[8] && + _indoorList._objects9._frame == -1) { + _indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][9]; + _indoorList._objects9._y = INDOOR_OBJECT_Y[listOffset][9]; + _indoorList._objects9._frame = mazeObject._frame; + _indoorList._objects9._sprites = mazeObject._sprites; + _indoorList._objects9._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects9._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Block 11 + pt = Common::Point(mazePos.x + posOffset[29], mazePos.y + posOffset[221]); + if (pt == mazeObject._position && !_wo[27] && !_wo[22] && (!_wo[15] || !_wo[19]) && + (!_wo[15] || !_wo[14]) && (!_wo[14] || !_wo[9]) && (!_wo[19] || !_wo[9]) && + _indoorList._objects10._frame == -1) { + _indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][10]; + _indoorList._objects10._y = INDOOR_OBJECT_Y[listOffset][10]; + _indoorList._objects10._frame = mazeObject._frame; + _indoorList._objects10._sprites = mazeObject._sprites; + _indoorList._objects10._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects10._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Block 12 + pt = Common::Point(mazePos.x + posOffset[31], mazePos.y + posOffset[223]); + if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[21]) && (!_wo[22] || !_wo[24]) && + (!_wo[21] || !_wo[19]) && (!_wo[24] || !_wo[19]) && !_wo[14] && !_wo[10] && + _indoorList._objects11._frame == -1) { + _indoorList._objects11._x = INDOOR_OBJECT_X[listOffset][11]; + _indoorList._objects11._y = INDOOR_OBJECT_Y[listOffset][11]; + _indoorList._objects11._frame = mazeObject._frame; + _indoorList._objects11._sprites = mazeObject._sprites; + _indoorList._objects11._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects11._flags |= SPRFLAG_HORIZ_FLIPPED; + } } } diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 3bb0fa7463..404beca2f1 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -99,8 +99,8 @@ private: bool _flag2; byte _tillMove; int _objNumber; - bool _objectFlag2, _objectFlag3, _objectFlag4, _objectFlag5; - bool _objectFlag6, _objectFlag7, _objectFlag8; + byte _wp[20]; + byte _wo[308]; void loadSprites(); -- cgit v1.2.3 From 892a504009e0d7d6d6304d485bf2fad9519781e9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 11 Jan 2015 18:29:36 -0500 Subject: XEEN: Implemented loading of object animation data --- engines/xeen/interface.cpp | 11 ++++++++++ engines/xeen/map.cpp | 53 +++++++++++++++++++++++++++++++++++++++++----- engines/xeen/map.h | 25 +++++++++++++++++++++- 3 files changed, 83 insertions(+), 6 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index b003e9aedd..665ce6728d 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -868,6 +868,17 @@ void Interface::draw3d(bool flag) { moveMonsters(); } + int e3 = 0xE302 + _objNumber * 8; + Direction dir = _vm->_party._mazeDirection; + bool flag2 = _flag2; + int objNum = _objNumber - 1; + + for (uint i = 0; i < _vm->_map->_mobData._objects.size(); ++i) { + if (flag2) { + + } + } + // TODO: more warning("TODO"); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index c70b0cfe6d..836680c24f 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -809,6 +809,49 @@ void HeadData::synchronize(Common::SeekableReadStream &s) { /*------------------------------------------------------------------------*/ +/** + * Synchronize data for an entry within an animation entry + */ +void AnimationFrame::synchronize(Common::SeekableReadStream &s) { + _left = s.readByte(); + _back = s.readByte(); + _right = s.readByte(); + _front = s.readByte(); +} + +/** + * Synchronize data for an animation entry + */ +void AnimationEntry::synchronize(Common::SeekableReadStream &s) { + _frame1.synchronize(s); + _flipped.synchronize(s); + _frame2.synchronize(s); +} + +/** + * Synchronize data for object animations within the game + */ +void AnimationInfo::synchronize(Common::SeekableReadStream &s) { + AnimationEntry entry; + + clear(); + while (s.pos() < s.size()) { + entry.synchronize(s); + push_back(entry); + } +} + +/** + * Load the animation info objects in the game + */ +void AnimationInfo::load(const Common::String &name) { + File f(name); + synchronize(f); + f.close(); +} + +/*------------------------------------------------------------------------*/ + Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { _townPortalSide = 0; _sideObj = 0; @@ -849,7 +892,7 @@ void Map::load(int mapId) { if (_vm->getGameID() == GType_WorldOfXeen) { if (_vm->_loadDarkSide) { - _objPicSprites.load("clouds.dat"); + _animationInfo.load("clouds.dat"); _monsterData.load("xeen.mon"); _wallPicSprites.load("xeenpic.dat"); } else { @@ -859,7 +902,7 @@ void Map::load(int mapId) { case 115: case 116: case 128: - _objPicSprites.load("clouds.dat"); + _animationInfo.load("clouds.dat"); _monsterData.load("dark.mon"); _wallPicSprites.load("darkpic.dat"); _sideObj = 0; @@ -869,7 +912,7 @@ void Map::load(int mapId) { case 119: case 120: case 124: - _objPicSprites.load("clouds.dat"); + _animationInfo.load("clouds.dat"); _monsterData.load("xeen.mon"); _wallPicSprites.load("darkpic.dat"); _sideObj = 0; @@ -878,12 +921,12 @@ void Map::load(int mapId) { case 125: case 126: case 127: - _objPicSprites.load("clouds.dat"); + _animationInfo.load("clouds.dat"); _monsterData.load("dark.mon"); _wallPicSprites.load("xeenpic.dat"); break; default: - _objPicSprites.load("dark.dat"); + _animationInfo.load("dark.dat"); _monsterData.load("ddark.mon"); _wallPicSprites.load("darkpic.dat"); break; diff --git a/engines/xeen/map.h b/engines/xeen/map.h index d26dffff82..228dfb8e22 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -311,13 +311,36 @@ public: void synchronize(Common::SeekableReadStream &s); }; +struct AnimationFrame { + int _front, _left, _back, _right; + + AnimationFrame(): _front(0), _left(0), _back(0), _right(0) {} + + void synchronize(Common::SeekableReadStream &s); +}; + +struct AnimationEntry { + AnimationFrame _frame1; + AnimationFrame _flipped; + AnimationFrame _frame2; + + void synchronize(Common::SeekableReadStream &s); +}; + +class AnimationInfo : public Common::Array<AnimationEntry> { +public: + void synchronize(Common::SeekableReadStream &s); + + void load(const Common::String &name); +}; + class Map { private: XeenEngine *_vm; MazeData _mazeData[9]; Common::String _mazeName; HeadData _headData; - SpriteResource _objPicSprites; + AnimationInfo _animationInfo; MonsterData _monsterData; SpriteResource _wallPicSprites; int _townPortalSide; -- cgit v1.2.3 From 1b3473d3431ae8fcac15526f1a59f1dfd0c9fc58 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 11 Jan 2015 19:30:02 -0500 Subject: XEEN: Implement frame update loop of draw3d --- engines/xeen/interface.cpp | 26 +++++++++++++++++++++----- engines/xeen/interface.h | 3 ++- engines/xeen/map.cpp | 19 ++++++------------- engines/xeen/map.h | 29 ++++++++++++++++------------- engines/xeen/resources.cpp | 4 ++++ engines/xeen/resources.h | 2 ++ 6 files changed, 51 insertions(+), 32 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 665ce6728d..9e02806750 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -361,7 +361,8 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { _intrIndex1 = 0; _flipWtr = false; _flag1 = false; - _flag2 = false; + _animCounter = 0; + _isAnimReset = false; _tillMove = 0; _objNumber = 0; @@ -868,15 +869,30 @@ void Interface::draw3d(bool flag) { moveMonsters(); } - int e3 = 0xE302 + _objNumber * 8; - Direction dir = _vm->_party._mazeDirection; - bool flag2 = _flag2; + MazeObject &objObject = _vm->_map->_mobData._objects[_objNumber]; + Direction partyDirection = _vm->_party._mazeDirection; int objNum = _objNumber - 1; for (uint i = 0; i < _vm->_map->_mobData._objects.size(); ++i) { - if (flag2) { + MazeObject &mazeObject = _vm->_map->_mobData._objects[i]; + AnimationEntry &animEntry = _vm->_map->_animationInfo[mazeObject._spriteId]; + int directionIndex = DIRECTION_ANIM_POSITIONS[mazeObject._direction][partyDirection]; + if (_isAnimReset) { + mazeObject._frame = animEntry._frame1._frames[directionIndex]; + } else { + ++mazeObject._frame; + if (i == objNum && _animCounter > 0 && ( + objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) || + objObject._spriteId == 58 || objObject._spriteId == 73)) { + if (mazeObject._frame > 4 || mazeObject._spriteId == 58) + mazeObject._frame = 1; + } else if (mazeObject._frame == animEntry._frame2._frames[directionIndex]) { + mazeObject._frame = animEntry._frame2._frames[directionIndex]; + } } + + mazeObject._flipped = animEntry._flipped._flags[directionIndex]; } // TODO: more diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 404beca2f1..d161169d68 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -96,7 +96,8 @@ private: int _intrIndex1; bool _flipWtr; bool _flag1; - bool _flag2; + int _animCounter; + bool _isAnimReset; byte _tillMove; int _objNumber; byte _wp[20]; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 836680c24f..b8ea36b698 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -809,23 +809,16 @@ void HeadData::synchronize(Common::SeekableReadStream &s) { /*------------------------------------------------------------------------*/ -/** - * Synchronize data for an entry within an animation entry - */ -void AnimationFrame::synchronize(Common::SeekableReadStream &s) { - _left = s.readByte(); - _back = s.readByte(); - _right = s.readByte(); - _front = s.readByte(); -} - /** * Synchronize data for an animation entry */ void AnimationEntry::synchronize(Common::SeekableReadStream &s) { - _frame1.synchronize(s); - _flipped.synchronize(s); - _frame2.synchronize(s); + for (int i = 0; i < 4; ++i) + _frame1._frames[i] = s.readByte(); + for (int i = 0; i < 4; ++i) + _flipped._flags[i] = s.readByte() != 0; + for (int i = 0; i < 4; ++i) + _frame2._frames[i] = s.readByte(); } /** diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 228dfb8e22..7255552d5d 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -311,18 +311,21 @@ public: void synchronize(Common::SeekableReadStream &s); }; -struct AnimationFrame { - int _front, _left, _back, _right; - - AnimationFrame(): _front(0), _left(0), _back(0), _right(0) {} - - void synchronize(Common::SeekableReadStream &s); -}; - +struct AnimationFrame { int _front, _left, _back, _right; }; +struct AnimationFlipped { bool _front, _left, _back, _right; }; struct AnimationEntry { - AnimationFrame _frame1; - AnimationFrame _flipped; - AnimationFrame _frame2; + union { + AnimationFrame _positions; + int _frames[4]; + } _frame1; + union { + AnimationFlipped _positions; + bool _flags[4]; + } _flipped; + union { + AnimationFrame _positions; + int _frames[4]; + } _frame2; void synchronize(Common::SeekableReadStream &s); }; @@ -339,8 +342,6 @@ private: XeenEngine *_vm; MazeData _mazeData[9]; Common::String _mazeName; - HeadData _headData; - AnimationInfo _animationInfo; MonsterData _monsterData; SpriteResource _wallPicSprites; int _townPortalSide; @@ -358,6 +359,8 @@ public: bool _isOutdoors; MonsterObjectData _mobData; MazeEvents _events; + HeadData _headData; + AnimationInfo _animationInfo; bool _currentIsGrate; bool _currentCantRest; bool _currentIsDrain; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 35fa2cb2bf..e660014ec3 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -350,4 +350,8 @@ const int OUTDOOR_OBJECT_Y[2][12] = { { 70, 71, 72, 73, 74, 75, 90, 91, 92, 93, 94, 112 } }; +const int DIRECTION_ANIM_POSITIONS[4][4] = { + { 0, 1, 2, 3 }, { 3, 0, 1, 2 }, { 2, 3, 0, 1 }, { 1, 2, 3, 0 } +}; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index d8cc93b9f4..35b82566b3 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -78,6 +78,8 @@ extern const int OUTDOOR_OBJECT_X[2][12]; extern const int OUTDOOR_OBJECT_Y[2][12]; +extern const int DIRECTION_ANIM_POSITIONS[4][4]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From d8e23aa558ffda15e36d087dee6e3f3d1db659ff Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 11 Jan 2015 20:35:32 -0500 Subject: XEEN: Split up SCREEN_POSITIONING array and fix data --- engines/xeen/interface.cpp | 47 +++++++++++++++++++++++++++++- engines/xeen/interface.h | 19 +++++++++++-- engines/xeen/resources.cpp | 71 ++++++++++++++++++++++++++++++---------------- engines/xeen/resources.h | 4 ++- 4 files changed, 112 insertions(+), 29 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 9e02806750..0ae64ca9c0 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -363,6 +363,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { _flag1 = false; _animCounter = 0; _isAnimReset = false; + _charsShooting = false; _tillMove = 0; _objNumber = 0; @@ -873,6 +874,8 @@ void Interface::draw3d(bool flag) { Direction partyDirection = _vm->_party._mazeDirection; int objNum = _objNumber - 1; + // Loop to update the frame numbers for each maze object, applying the animation frame + // limits as specified by the map's _animationInfo listing for (uint i = 0; i < _vm->_map->_mobData._objects.size(); ++i) { MazeObject &mazeObject = _vm->_map->_mobData._objects[i]; AnimationEntry &animEntry = _vm->_map->_animationInfo[mazeObject._spriteId]; @@ -895,6 +898,40 @@ void Interface::draw3d(bool flag) { mazeObject._flipped = animEntry._flipped._flags[directionIndex]; } + if (_vm->_map->_isOutdoors) { + error("TODO: draw3d outdoors handling"); + } else { + // Default all the parts of draw struct not to be drawn by default + for (int idx = 3; idx < _indoorList.size(); ++idx) + _indoorList[idx]._frame = -1; + + if (_flag1) { + for (int idx = 0; idx < 96; ++idx) { + if (_indoorList[79 + idx]._sprites != nullptr) { + _indoorList[79 + idx]._frame = 0; + } else if (_indoorList[111 + idx]._sprites != nullptr) { + _indoorList[111 + idx]._frame = 1; + } else if (_indoorList[135 + idx]._sprites != nullptr) { + _indoorList[135 + idx]._frame = 2; + } else if (_indoorList[162 + idx]._sprites != nullptr) { + _indoorList[162 + idx]._frame = 0; + } + } + } else if (_charsShooting) { + for (int idx = 0; idx < 96; ++idx) { + if (_indoorList[162 + idx]._sprites != nullptr) { + _indoorList[162 + idx]._frame = 0; + } else if (_indoorList[135 + idx]._sprites != nullptr) { + _indoorList[135 + idx]._frame = 1; + } else if (_indoorList[111 + idx]._sprites != nullptr) { + _indoorList[111 + idx]._frame = 2; + } else if (_indoorList[79 + idx]._sprites != nullptr) { + _indoorList[79 + idx]._frame = 0; + } + } + } + } + // TODO: more warning("TODO"); @@ -911,7 +948,7 @@ void Interface::setIndoorsMonsters() { void Interface::setIndoorObjects() { Common::Point mazePos = _vm->_party._mazePosition; _objNumber = 0; - const int8 *posOffset = &SCREEN_POSITIONING[_vm->_party._mazeDirection * 48]; + const int8 *posOffset = &SCREEN_POSITIONING_X[_vm->_party._mazeDirection][0]; Common::Point pt; Common::Array<MazeObject> &objects = _vm->_map->_mobData._objects; @@ -1158,4 +1195,12 @@ void Interface::setMainButtons() { addButton(Common::Rect(239, 47, 312, 57), 51, &_iconSprites, false); } +void Interface::setMazeBits() { + +} + +void Interface::getCell() { +} + + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index d161169d68..1c110352bb 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -40,7 +40,12 @@ public: public: OutdoorDrawList(); - DrawStruct &operator[](int idx) { return _data[idx]; } + DrawStruct &operator[](int idx) { + assert(idx < size()); + return _data[idx]; + } + + int size() const { return 132; } }; class IndoorDrawList { @@ -54,7 +59,12 @@ public: public: IndoorDrawList(); - DrawStruct &operator[](int idx) { return _data[idx]; } + DrawStruct &operator[](int idx) { + assert(idx < size()); + return _data[idx]; + } + + int size() const { return 170; } }; @@ -98,6 +108,7 @@ private: bool _flag1; int _animCounter; bool _isAnimReset; + bool _charsShooting; byte _tillMove; int _objNumber; byte _wp[20]; @@ -132,6 +143,10 @@ private: void moveMonsters(); void setMainButtons(); + + void setMazeBits(); + + void getCell(); public: Interface(XeenEngine *vm); diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index e660014ec3..0737e1462d 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -303,31 +303,52 @@ const char *const PLEASE_WAIT = "\014""d\003""c\011""000" const char *const OOPS = "\003""c\011""000\013""002Oops..."; -const int8 SCREEN_POSITIONING[384] = { - -1, 0, 0, 0, 1, -1, 0, 0, 0, 1, -2, -1, -1, 0, 0, 0, - 1, 1, 2, -4, -3, -3, -2, -2, -1, -1, 0, 0, 0, 1, 1, 2, - 2, 3, 3, 4, -3, -2, -1, 0, 0, 1, 2, 3, -4, 4, 0, 0, - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1, - 1, 0, 0, 0, -1, 1, 0, 0, 0, -1, 2, 1, 1, 0, 0, 0, - -1, -1, -2, 4, 3, 3, 2, 2, 1, 1, 0, 0, 0, -1, -1, -2, - -2, -3, -3, -4, 3, 2, 1, 0, 0, -1, -2, -3, 4, -4, 0, 0, - 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, - -2, -2, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, - -3, -3, -3, -3, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, 0, -1, - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1, - 1, 0, 0, 0, -1, 1, 0, 0, 0, -1, 2, 1, 1, 0, 0, 0, - -1, -1, -2, 4, 3, 3, 2, 2, 1, 1, 0, 0, 0, -1, -1, -2, - -2, -3, -3, -4, 3, 2, 1, 0, 0, -1, -2, -3, 4, -4, 0, 0, - 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, - -2, -2, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, - -3, -3, -3, -3, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, 0, -1, - -1, 0, 0, 0, 1, -1, 0, 0, 0, 1, -2, -1, -1, 0, 0, 0, - 1, 1, 2, -4, -3, -3, -2, -2, -1, -1, 0, 0, 0, 1, 1, 2, - 2, 3, 3, 4, -3, -2, -1, 0, 0, 1, 2, 3, -4, 4, 0, 0, +const int8 SCREEN_POSITIONING_X[4][48] = { + { + -1, 0, 0, 0, 1, -1, 0, 0, 0, 1, -2, -1, + -1, 0, 0, 0, 1, 1, 2, -4, -3, -3, -2, -2, + -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, + -3, -2, -1, 0, 0, 1, 2, 3, -4, 4, 0, 0 + }, { + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1 + }, { + 1, 0, 0, 0, -1, 1, 0, 0, 0, -1, 2, 1, + 1, 0, 0, 0, -1, -1, -2, 4, 3, 3, 2, 2, + 1, 1, 0, 0, 0, -1, -1, -2, -2, -3, -3, -4, + 3, 2, 1, 0, 0, -1, -2, -3, 4, -4, 0, 0 + }, { + 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -3, -3, -3, -3, -3, + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, + -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, 0, -1 + } +}; + +const int8 SCREEN_POSITIONING_Y[4][48] = { + { + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1 + }, { + 1, 0, 0, 0, -1, 1, 0, 0, 0, -1, 2, 1, + 1, 0, 0, 0, -1, -1, -2, 4, 3, 3, 2, 2, + 1, 1, 0, 0, 0, -1, -1, -2, -2, -3, -3, -4, + 3, 2, 1, 0, 0, -1, -2, -3, 4, -4, 0, 0 + }, { + 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -3, -3, -3, -3, -3, + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, + -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, 0, -1 + }, { + -1, 0, 0, 0, 1, -1, 0, 0, 0, 1, -2, -1, + -1, 0, 0, 0, 1, 1, 2, -4, -3, -3, -2, -2, + -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, + -3, -2, -1, 0, 0, 1, 2, 3, -4, 4, 0, 0 + } }; const int INDOOR_OBJECT_X[2][12] = { diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 35b82566b3..36c2cb0e12 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -68,7 +68,9 @@ extern const char *const PLEASE_WAIT; extern const char *const OOPS; -extern const int8 SCREEN_POSITIONING[384]; +extern const int8 SCREEN_POSITIONING_X[4][48]; + +extern const int8 SCREEN_POSITIONING_Y[4][48]; extern const int INDOOR_OBJECT_X[2][12]; -- cgit v1.2.3 From 230c4f52ea8f5c95ea28a5f25bcf5c6f89acbd60 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 11 Jan 2015 23:55:46 -0500 Subject: XEEN: Implemented map getCell method --- engines/xeen/interface.cpp | 6 +-- engines/xeen/interface.h | 2 - engines/xeen/map.cpp | 130 +++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/map.h | 4 ++ engines/xeen/resources.cpp | 40 ++++++++++++++ engines/xeen/resources.h | 2 + 6 files changed, 177 insertions(+), 7 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 0ae64ca9c0..4fb943fde5 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -885,7 +885,7 @@ void Interface::draw3d(bool flag) { mazeObject._frame = animEntry._frame1._frames[directionIndex]; } else { ++mazeObject._frame; - if (i == objNum && _animCounter > 0 && ( + if ((int)i == objNum && _animCounter > 0 && ( objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) || objObject._spriteId == 58 || objObject._spriteId == 73)) { if (mazeObject._frame > 4 || mazeObject._spriteId == 58) @@ -1199,8 +1199,4 @@ void Interface::setMazeBits() { } -void Interface::getCell() { -} - - } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 1c110352bb..d50cdd029b 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -145,8 +145,6 @@ private: void setMainButtons(); void setMazeBits(); - - void getCell(); public: Interface(XeenEngine *vm); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index b8ea36b698..b6bf91db57 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -854,6 +854,8 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { _mazeDataIndex = 0; _currentSteppedOn = false; _currentSurfaceId = 0; + _currentWall = 0; + _currentTile = 0; _currentIsGrate = false; _currentCantRest = false; _currentIsDrain = false; @@ -1217,4 +1219,132 @@ void Map::setCellSurfaceFlags(const Common::Point &pt, int bits) { _mazeData[0]._cells[pt.y][pt.x]._surfaceId |= bits; } + +int Map::getCell(int idx) { + int mapId = _vm->_party._mazeId; + Direction dir = _vm->_party._mazeDirection; + Common::Point pt( + _vm->_party._mazePosition.x + SCREEN_POSITIONING_X[_vm->_party._mazeDirection][idx], + _vm->_party._mazePosition.y + SCREEN_POSITIONING_Y[_vm->_party._mazeDirection][idx] + ); + + if (pt.x > 31 || pt.y > 31) { + if (_vm->_files->_isDarkCc) { + if ((mapId >= 53 && mapId <= 88 && mapId != 73) || (mapId >= 74 && mapId <= 120) || + mapId == 125 || mapId == 126 || mapId == 128 || mapId == 129) { + _currentSurfaceId = SURFTYPE_DESERT; + } else { + _currentSurfaceId = 0; + } + } else { + _currentSurfaceId = (mapId >= 25 && mapId <= 27) ? 7 : 0; + } + _currentWall = 0x8888; + return _currentWall; + } + + _mazeDataIndex = 0; + while (_mazeData[_mazeDataIndex]._mazeId != mapId) + ++_mazeDataIndex; + + if (pt.y & 16) { + if (pt.y >= 0) { + pt.y -= 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._north; + } else { + pt.y += 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._south; + } + + if (!mapId) { + if (_isOutdoors) { + _currentSurfaceId = SURFTYPE_SPACE; + _currentWall = 0; + return 0; + } else { + if (_vm->_files->_isDarkCc) { + if ((mapId >= 53 && mapId <= 88 && mapId != 73) || (mapId >= 74 && mapId <= 120) || + mapId == 125 || mapId == 126 || mapId == 128 || mapId == 129) { + _currentSurfaceId = SURFTYPE_DESERT; + } else { + _currentSurfaceId = 0; + } + } else { + _currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT; + } + + _currentWall = 0x8888; + return _currentWall; + } + + _mazeDataIndex = 0; + while (_mazeData[_mazeDataIndex]._mazeId != mapId) + ++_mazeDataIndex; + } + } + + if (pt.x & 16) { + if (pt.x >= 0) { + pt.x -= 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._east; + } else { + pt.x += 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._east; + } + + if (!mapId) { + if (_isOutdoors) { + _currentSurfaceId = SURFTYPE_SPACE; + _currentWall = 0; + return _currentWall; + } else { + if (_vm->_files->_isDarkCc) { + if ((mapId >= 53 && mapId <= 88 && mapId != 73) || (mapId >= 74 && mapId <= 120) || + mapId == 125 || mapId == 126 || mapId == 128 || mapId == 129) { + _currentSurfaceId = SURFTYPE_DESERT; + } else { + _currentSurfaceId = 0; + } + } else { + _currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT; + } + + _currentWall = 0x8888; + return _currentWall; + } + + _mazeDataIndex = 0; + while (_mazeData[_mazeDataIndex]._mazeId != mapId) + ++_mazeDataIndex; + } + } + + MazeWallLayers &wallLayers = _mazeData[_mazeDataIndex]._wallData[pt.y][pt.x]; + if (_isOutdoors) { + if (mapId) { + // TODO: tile is set to word of (wallLayers >> 8) && 0xff? Makes no sense + _currentTile = wallLayers._outdoors._surfaceId; + _currentWall = wallLayers._outdoors._iMiddle; + _currentSurfaceId = wallLayers._outdoors._surfaceId; + } else { + _currentSurfaceId = SURFTYPE_DEFAULT; + _currentWall = 0; + _currentTile = 0; + } + } else { + if (!mapId) + return 0; + + if (pt.x > 31 || pt.y > 31) + _currentSurfaceId = SURFTYPE_ROAD; + else + _currentSurfaceId = _mazeData[_mazeDataIndex]._cells[pt.y][pt.x]._surfaceId; + + _currentWall = wallLayers._data; + return (_currentWall >> (WALL_NUMBERS[dir][idx * 2] * 4)) & 0xF; + } + + return _currentWall; +} + } // End of namespace Xeen diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 7255552d5d..17c3fc684f 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -351,6 +351,8 @@ private: int _mazeDataIndex; bool _currentSteppedOn; int _currentSurfaceId; + int _currentWall; + int _currentTile; void loadEvents(int mapId); @@ -377,6 +379,8 @@ public: void setCellSurfaceFlags(const Common::Point &pt, int bits); void saveMaze(); + + int getCell(int idx); }; } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 0737e1462d..352e59620c 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -375,4 +375,44 @@ const int DIRECTION_ANIM_POSITIONS[4][4] = { { 0, 1, 2, 3 }, { 3, 0, 1, 2 }, { 2, 3, 0, 1 }, { 1, 2, 3, 0 } }; +const byte WALL_NUMBERS[4][96] = { + { + 3, 0, 0, 0, 3, 0, 2, 0, 3, 0, 3, 0, + 0, 0, 3, 0, 2, 0, 3, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 2, 0, 3, 0, 2, 0, + 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, 3, 0, 2, 0, 3, 0, + 2, 0, 3, 0, 2, 0, 3, 0, 2, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 0, 0, 0, 0, 1, 0, 1, 0 + }, { + 2, 0, 3, 0, 2, 0, 1, 0, 2, 0, 2, 0, + 3, 0, 2, 0, 1, 0, 2, 0, 2, 0, 3, 0, + 2, 0, 3, 0, 2, 0, 1, 0, 2, 0, 1, 0, + 2, 0, 2, 0, 3, 0, 2, 0, 3, 0, 2, 0, + 3, 0, 2, 0, 3, 0, 2, 0, 1, 0, 2, 0, + 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, + 3, 0, 3, 0, 3, 0, 3, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, { + 1, 0, 2, 0, 1, 0, 0, 0, 1, 0, 1, 0, + 2, 0, 1, 0, 0, 0, 1, 0, 1, 0, 2, 0, + 1, 0, 2, 0, 1, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, + 2, 0, 1, 0, 2, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0 + }, { + 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 3, 0, + 3, 0, 3, 0, 0, 0, 0, 0, 2, 0, 2, 0 + } +}; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 36c2cb0e12..2c537fd890 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -82,6 +82,8 @@ extern const int OUTDOOR_OBJECT_Y[2][12]; extern const int DIRECTION_ANIM_POSITIONS[4][4]; +extern const byte WALL_NUMBERS[4][96]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From 488847006c5ddd29a6ab8de0145d80e26daab48c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 12 Jan 2015 20:25:12 -0500 Subject: XEEN: Implemented setMazeBits --- engines/xeen/interface.cpp | 1494 +++++++++++++++++++++++++++++++++++++++++++- engines/xeen/interface.h | 1 + engines/xeen/map.h | 4 +- engines/xeen/xeen.cpp | 1 - engines/xeen/xeen.h | 1 - 5 files changed, 1496 insertions(+), 5 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 4fb943fde5..46b7bc4c58 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -366,6 +366,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { _charsShooting = false; _tillMove = 0; _objNumber = 0; + _thinWall = false; Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); Common::fill(&_wp[0], &_wp[20], 0); @@ -639,7 +640,7 @@ void Interface::assembleBorder() { // Draw UI element to indicate whether can spot hidden doors _borderSprites.draw(screen, - (_vm->_thinWall && _vm->_party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, + (_thinWall && _vm->_party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, Common::Point(194, 91)); _spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12; @@ -1196,7 +1197,1498 @@ void Interface::setMainButtons() { } void Interface::setMazeBits() { + Common::fill(&_wo[0], &_wo[308], 0); + + switch (_vm->_map->getCell(0)) { + case 0: + ++_wo[125]; + break; + case 1: + ++_wo[69]; + break; + case 2: + ++_wo[185]; + break; + case 3: + case 12: + ++_wo[105]; + break; + case 4: + case 7: + ++_wo[25]; + break; + case 5: + ++_wo[225]; + break; + case 6: + ++_wo[205]; + break; + case 8: + ++_wo[145]; + break; + case 9: + ++_wo[305]; + break; + case 10: + ++_wo[245]; + break; + case 11: + ++_wo[165]; + break; + case 13: + ++_wo[265]; + break; + case 14: + ++_wo[285]; + break; + default: + break; + } + + switch (_vm->_map->getCell(1)) { + case 1: + ++_wo[72]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[28]; + break; + default: + break; + } + + switch (_vm->_map->getCell(2)) { + case 0: + ++_wo[127]; + break; + case 1: + ++_wo[71]; + break; + case 2: + ++_wo[187]; + break; + case 3: + case 12: + ++_wo[107]; + break; + case 4: + case 7: + _wo[27]; + break; + case 5: + ++_wo[227]; + break; + case 6: + ++_wo[207]; + break; + case 8: + ++_wo[147]; + break; + case 9: + ++_wo[307]; + break; + case 10: + ++_wo[247]; + break; + case 11: + ++_wo[167]; + break; + case 13: + ++_wo[267]; + break; + case 14: + ++_wo[287]; + break; + defualt: + break; + } + + switch (_vm->_map->getCell(3)) { + case 1: + ++_wo[73]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[29]; + break; + default: + break; + } + + switch (_vm->_map->getCell(4)) { + case 0: + ++_wo[126]; + break; + case 1: + ++_wo[70]; + break; + case 2: + ++_wo[186]; + break; + case 3: + case 12: + ++_wo[106]; + break; + case 4: + case 7: + ++_wo[26]; + break; + case 5: + ++_wo[226]; + break; + case 6: + ++_wo[206]; + case 8: + ++_wo[146]; + break; + case 9: + ++_wo[306]; + break; + case 10: + ++_wo[246]; + break; + break; + case 11: + ++_wo[166]; + break; + case 13: + ++_wo[266]; + break; + case 14: + ++_wo[286]; + break; + default: + break; + } + + switch (_vm->_map->getCell(5)) { + case 0: + ++_wo[122]; + break; + case 1: + ++_wo[64]; + break; + case 2: + ++_wo[182]; + break; + case 3: + case 12: + ++_wo[102]; + break; + case 5: + ++_wo[222]; + break; + case 6: + ++_wo[202]; + break; + case 8: + ++_wo[142]; + break; + case 9: + ++_wo[302]; + break; + case 10: + ++_wo[242]; + break; + case 11: + ++_wo[162]; + break; + case 13: + ++_wo[262]; + break; + case 14: + ++_wo[282]; + break; + default: + break; + } + + switch (_vm->_map->getCell(6)) { + case 1: + ++_wo[67]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[23]; + break; + default: + break; + } + + switch (_vm->_map->getCell(7)) { + case 0: + ++_wo[124]; + break; + case 1: + ++_wo[66]; + break; + case 2: + ++_wo[184]; + break; + case 3: + case 12: + ++_wo[104]; + break; + case 4: + case 7: + ++_wo[22]; + break; + case 5: + ++_wo[224]; + break; + case 6: + ++_wo[204]; + break; + case 8: + ++_wo[144]; + break; + case 9: + ++_wo[304]; + break; + case 10: + ++_wo[244]; + break; + case 11: + ++_wo[164]; + break; + case 13: + ++_wo[264]; + break; + case 14: + ++_wo[284]; + break; + default: + break; + } + + _thinWall = (_vm->_map->_currentWall != 0x8888 && _wo[27]); + + switch (_vm->_map->getCell(8)) { + case 1: + ++_wo[68]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[24]; + break; + default: + break; + } + + switch (_vm->_map->getCell(9)) { + case 0: + ++_wo[123]; + break; + case 1: + ++_wo[65]; + break; + case 2: + ++_wo[183]; + break; + case 3: + case 12: + ++_wo[103]; + break; + case 4: + case 7: + ++_wo[21]; + break; + case 5: + ++_wo[223]; + break; + case 6: + ++_wo[203]; + break; + case 8: + ++_wo[143]; + break; + case 9: + ++_wo[3033]; + break; + case 10: + ++_wo[243]; + break; + case 11: + ++_wo[163]; + break; + case 13: + ++_wo[263]; + break; + case 14: + ++_wo[283]; + break; + default: + break; + } + + switch (_vm->_map->getCell(10)) { + case 0: + +_wo[117]; + break; + case 1: + ++_wo[55]; + break; + case 2: + ++_wo[177]; + break; + case 3: + case 12: + ++_wo[97]; + break; + case 4: + case 7: + ++_wo[11]; + break; + case 5: + ++_wo[217]; + break; + case 6: + ++_wo[197]; + break; + case 8: + ++_wo[137]; + break; + case 9: + ++_wo[297]; + break; + case 10: + ++_wo[237]; + case 11: + ++_wo[157]; + break; + case 13: + ++_wo[257]; + break; + case 14: + ++_wo[277]; + break; + default: + break; + } + + switch (_vm->_map->getCell(11)) { + case 1: + ++_wo[60]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[16]; + break; + default: + break; + } + + switch (_vm->_map->getCell(12)) { + case 0: + ++_wo[118]; + break; + case 1: + ++_wo[56]; + break; + case 2: + ++_wo[178]; + break; + case 3: + case 12: + ++_wo[98]; + break; + case 4: + case 7: + ++_wo[12]; + break; + case 5: + ++_wo[218]; + break; + case 6: + ++_wo[198]; + break; + case 8: + ++_wo[138]; + break; + case 9: + ++_wo[298]; + break; + case 10: + ++_wo[238]; + break; + case 11: + ++_wo[158]; + break; + case 13: + ++_wo[258]; + break; + case 14: + ++_wo[278]; + break; + default: + break; + } + + switch (_vm->_map->getCell(13)) { + case 1: + ++_wo[61]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[17]; + break; + default: + break; + } + + switch (_vm->_map->getCell(14)) { + case 0: + ++_wo[121]; + break; + case 1: + ++_wo[59]; + break; + case 2: + ++_wo[181]; + break; + case 3: + case 12: + ++_wo[101]; + break; + case 4: + case 7: + ++_wo[15]; + break; + case 5: + ++_wo[221]; + break; + case 6: + ++_wo[201]; + break; + case 8: + ++_wo[141]; + break; + case 9: + ++_wo[301]; + break; + case 10: + ++_wo[241]; + break; + case 11: + ++_wo[161]; + break; + case 13: + ++_wo[261]; + break; + case 14: + ++_wo[281]; + break; + default: + break; + } + + switch (_vm->_map->getCell(15)) { + case 1: + ++_wo[63]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[19]; + break; + default: + break; + } + + switch (_vm->_map->getCell(16)) { + case 0: + ++_wo[120]; + break; + case 1: + ++_wo[58]; + break; + case 2: + ++_wo[180]; + break; + case 3: + case 12: + ++_wo[100]; + break; + case 4: + case 7: + ++_wo[14]; + break; + case 5: + ++_wo[220]; + break; + case 6: + ++_wo[200]; + break; + case 8: + ++_wo[140]; + break; + case 9: + ++_wo[300]; + break; + case 10: + ++_wo[240]; + break; + case 11: + ++_wo[160]; + break; + case 13: + ++_wo[260]; + break; + case 14: + ++_wo[280]; + break; + default: + break; + } + + switch (_vm->_map->getCell(17)) { + case 1: + ++_wo[62]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[18]; + break; + default: + break; + } + + switch (_vm->_map->getCell(18)) { + case 0: + ++_wo[119]; + break; + case 1: + ++_wo[57]; + break; + case 2: + ++_wo[179]; + break; + case 3: + case 12: + ++_wo[99]; + break; + case 4: + case 7: + ++_wo[13]; + break; + case 5: + ++_wo[219]; + break; + case 6: + ++_wo[199]; + break; + case 8: + ++_wo[139]; + break; + case 9: + ++_wo[299]; + break; + case 10: + ++_wo[239]; + break; + case 11: + ++_wo[159]; + break; + case 13: + ++_wo[259]; + break; + case 14: + ++_wo[279]; + break; + default: + break; + } + + switch (_vm->_map->getCell(19)) { + case 0: + ++_wo[108]; + break; + case 1: + ++_wo[78]; + break; + case 2: + ++_wo[168]; + case 3: + case 12: + ++_wo[88]; + break; + case 4: + case 7: + ++_wo[34]; + break; + case 5: + ++_wo[208]; + break; + case 6: + ++_wo[188]; + break; + case 8: + ++_wo[128]; + break; + case 9: + ++_wo[288]; + break; + case 10: + ++_wo[228]; + break; + case 11: + ++_wo[148]; + break; + case 13: + ++_wo[248]; + break; + case 14: + ++_wo[268]; + break; + default: + break; + } + + switch (_vm->_map->getCell(20)) { + case 1: + ++_wo[76]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[32]; + break; + default: + break; + } + + switch (_vm->_map->getCell(21)) { + case 0: + ++_wo[109]; + break; + case 1: + ++_wo[44]; + break; + case 2: + ++_wo[169]; + break; + case 3: + case 12: + ++_wo[89]; + break; + case 4: + case 7: + ++_wo[0]; + break; + case 5: + ++_wo[209]; + break; + case 6: + ++_wo[189]; + break; + case 8: + ++_wo[129]; + break; + case 9: + ++_wo[289]; + break; + case 10: + ++_wo[229]; + break; + case 11: + ++_wo[149]; + break; + case 13: + ++_wo[249]; + break; + case 14: + ++_wo[269]; + break; + default: + break; + } + + switch (_vm->_map->getCell(22)) { + case 1: + ++_wo[74]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[30]; + break; + default: + break; + } + + switch (_vm->_map->getCell(23)) { + case 0: + ++_wo[110]; + break; + case 1: + ++_wo[45]; + break; + case 2: + ++_wo[170]; + break; + case 3: + case 12: + ++_wo[90]; + break; + case 4: + case 7: + ++_wo[1]; + break; + case 5: + ++_wo[210]; + break; + case 6: + ++_wo[190]; + break; + case 8: + ++_wo[130]; + break; + case 9: + ++_wo[290]; + break; + case 10: + ++_wo[230]; + break; + case 11: + ++_wo[150]; + break; + case 13: + ++_wo[250]; + break; + case 14: + ++_wo[270]; + break; + default: + break; + } + + switch (_vm->_map->getCell(24)) { + case 1: + ++_wo[52]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[8]; + break; + default: + break; + } + + switch (_vm->_map->getCell(25)) { + case 0: + ++_wo[111]; + break; + case 1: + ++_wo[46]; + break; + case 2: + ++_wo[171]; + break; + case 3: + case 12: + ++_wo[91]; + break; + case 4: + case 7: + ++_wo[2]; + break; + case 5: + ++_wo[211]; + break; + case 6: + ++_wo[191]; + break; + case 8: + ++_wo[131]; + break; + case 9: + ++_wo[291]; + break; + case 10: + ++_wo[231]; + break; + case 11: + ++_wo[151]; + break; + case 13: + ++_wo[251]; + break; + case 14: + ++_wo[271]; + break; + default: + break; + } + + switch (_vm->_map->getCell(26)) { + case 1: + ++_wo[51]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[7]; + break; + default: + break; + } + + switch (_vm->_map->getCell(27)) { + case 0: + ++_wo[116]; + break; + case 1: + ++_wo[50]; + break; + case 2: + ++_wo[176]; + break; + case 3: + case 12: + ++_wo[96]; + break; + case 4: + case 7: + ++_wo[6]; + break; + case 5: + ++_wo[216]; + break; + case 6: + ++_wo[196]; + break; + case 8: + ++_wo[136]; + break; + case 9: + ++_wo[296]; + break; + case 10: + ++_wo[236]; + break; + case 11: + ++_wo[156]; + break; + case 13: + ++_wo[256]; + break; + case 14: + ++_wo[276]; + break; + default: + break; + } + + switch (_vm->_map->getCell(28)) { + case 1: + ++_wo[53]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[9]; + break; + default: + break; + } + + switch (_vm->_map->getCell(29)) { + case 0: + ++_wo[115]; + break; + case 1: + ++_wo[49]; + break; + case 2: + ++_wo[175]; + break; + case 3: + case 12: + ++_wo[95]; + break; + case 4: + case 7: + ++_wo[5]; + break; + case 5: + ++_wo[215]; + break; + case 6: + ++_wo[195]; + break; + case 8: + ++_wo[135]; + break; + case 9: + ++_wo[295]; + break; + case 10: + ++_wo[235]; + break; + case 11: + ++_wo[155]; + break; + case 13: + ++_wo[255]; + break; + case 14: + ++_wo[275]; + break; + default: + break; + } + + switch (_vm->_map->getCell(30)) { + case 1: + ++_wo[54]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[10]; + break; + default: + break; + } + + switch (_vm->_map->getCell(31)) { + case 0: + ++_wo[114]; + break; + case 1: + ++_wo[48]; + break; + case 2: + ++_wo[174]; + break; + case 3: + case 12: + ++_wo[94]; + break; + case 4: + ++_wo[4]; + break; + case 5: + ++_wo[214]; + break; + case 6: + ++_wo[194]; + break; + case 8: + ++_wo[134]; + break; + case 9: + ++_wo[294]; + break; + case 10: + ++_wo[234]; + break; + case 11: + ++_wo[154]; + break; + case 13: + ++_wo[254]; + break; + case 14: + ++_wo[274]; + break; + default: + break; + } + + switch (_vm->_map->getCell(32)) { + case 1: + ++_wo[75]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[31]; + break; + default: + break; + } + + switch (_vm->_map->getCell(33)) { + case 0: + ++_wo[112]; + break; + case 1: + ++_wo[47]; + break; + case 2: + ++_wo[172]; + break; + case 3: + case 12: + ++_wo[92]; + break; + case 4: + case 7: + ++_wo[3]; + break; + case 5: + ++_wo[212]; + break; + case 6: + ++_wo[192]; + break; + case 8: + ++_wo[132]; + break; + case 9: + ++_wo[292]; + break; + case 10: + ++_wo[232]; + break; + case 11: + ++_wo[152]; + break; + case 13: + ++_wo[252]; + break; + case 14: + ++_wo[272]; + break; + default: + break; + } + + switch (_vm->_map->getCell(34)) { + case 1: + ++_wo[77]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[33]; + break; + default: + break; + } + + switch (_vm->_map->getCell(35)) { + case 0: + ++_wo[113]; + break; + case 1: + ++_wo[79]; + break; + case 2: + ++_wo[173]; + break; + case 3: + case 12: + ++_wo[93]; + break; + case 4: + case 7: + ++_wo[35]; + break; + case 5: + ++_wo[213]; + break; + case 6: + ++_wo[193]; + break; + case 8: + ++_wo[133]; + break; + case 9: + ++_wo[293]; + break; + case 10: + ++_wo[233]; + break; + case 11: + ++_wo[153]; + break; + case 13: + ++_wo[253]; + break; + case 14: + ++_wo[273]; + break; + default: + break; + } + + switch (_vm->_map->getCell(36)) { + case 1: + ++_wo[83]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[39]; + break; + default: + break; + } + + switch (_vm->_map->getCell(37)) { + case 1: + ++_wo[82]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[38]; + break; + default: + break; + } + switch (_vm->_map->getCell(38)) { + case 1: + ++_wo[81]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[37]; + break; + default: + break; + } + + switch (_vm->_map->getCell(34)) { + case 1: + ++_wo[80]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[36]; + break; + default: + break; + } + + switch (_vm->_map->getCell(40)) { + case 1: + ++_wo[84]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[40]; + break; + default: + break; + } + + switch (_vm->_map->getCell(41)) { + case 1: + ++_wo[85]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[41]; + break; + default: + break; + } + + switch (_vm->_map->getCell(42)) { + case 1: + ++_wo[86]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[42]; + break; + default: + break; + } + + switch (_vm->_map->getCell(43)) { + case 1: + ++_wo[87]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[43]; + break; + default: + break; + } } } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index d50cdd029b..bd2f2af4b7 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -113,6 +113,7 @@ private: int _objNumber; byte _wp[20]; byte _wo[308]; + bool _thinWall; void loadSprites(); diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 17c3fc684f..6a061788ac 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -351,8 +351,6 @@ private: int _mazeDataIndex; bool _currentSteppedOn; int _currentSurfaceId; - int _currentWall; - int _currentTile; void loadEvents(int mapId); @@ -369,6 +367,8 @@ public: bool _currentIsEvent; bool _currentIsObject; int _currentMonsterFlags; + int _currentWall; + int _currentTile; public: Map(XeenEngine *vm); diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 9cc51e1765..583a1dd262 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -46,7 +46,6 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _sound = nullptr; _eventData = nullptr; _loadDarkSide = 1; - _thinWall = false; _dangerSenseAllowed = false; _face1State = 0; _face2State = 0; diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index efeacf0ae1..a9b102aec2 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -138,7 +138,6 @@ public: Roster _roster; Party _party; int _loadDarkSide; - bool _thinWall; bool _dangerSenseAllowed; int _face1State; int _face2State; -- cgit v1.2.3 From 07f37cedf54d956d9f736012f5b334e26cdbac5d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 12 Jan 2015 20:56:15 -0500 Subject: XEEN: Change _currentWall to be MazeWallLayers union --- engines/xeen/interface.cpp | 6 +++--- engines/xeen/map.cpp | 32 ++++++++++++++++---------------- engines/xeen/map.h | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 46b7bc4c58..2dec248d54 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -1311,7 +1311,7 @@ void Interface::setMazeBits() { case 14: ++_wo[287]; break; - defualt: + default: break; } @@ -1497,7 +1497,7 @@ void Interface::setMazeBits() { break; } - _thinWall = (_vm->_map->_currentWall != 0x8888 && _wo[27]); + _thinWall = (_vm->_map->_currentWall._data != 0x8888) && _wo[27]; switch (_vm->_map->getCell(8)) { case 1: @@ -1571,7 +1571,7 @@ void Interface::setMazeBits() { switch (_vm->_map->getCell(10)) { case 0: - +_wo[117]; + ++_wo[117]; break; case 1: ++_wo[55]; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index b6bf91db57..f9a687b6ee 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -854,7 +854,7 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { _mazeDataIndex = 0; _currentSteppedOn = false; _currentSurfaceId = 0; - _currentWall = 0; + _currentWall._data = 0; _currentTile = 0; _currentIsGrate = false; _currentCantRest = false; @@ -1239,8 +1239,8 @@ int Map::getCell(int idx) { } else { _currentSurfaceId = (mapId >= 25 && mapId <= 27) ? 7 : 0; } - _currentWall = 0x8888; - return _currentWall; + _currentWall._data = 0x8888; + return 0x8888; } _mazeDataIndex = 0; @@ -1259,7 +1259,7 @@ int Map::getCell(int idx) { if (!mapId) { if (_isOutdoors) { _currentSurfaceId = SURFTYPE_SPACE; - _currentWall = 0; + _currentWall._data = 0; return 0; } else { if (_vm->_files->_isDarkCc) { @@ -1273,8 +1273,8 @@ int Map::getCell(int idx) { _currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT; } - _currentWall = 0x8888; - return _currentWall; + _currentWall._data = 0x8888; + return 0x8888; } _mazeDataIndex = 0; @@ -1295,8 +1295,8 @@ int Map::getCell(int idx) { if (!mapId) { if (_isOutdoors) { _currentSurfaceId = SURFTYPE_SPACE; - _currentWall = 0; - return _currentWall; + _currentWall._data = 0; + return 0; } else { if (_vm->_files->_isDarkCc) { if ((mapId >= 53 && mapId <= 88 && mapId != 73) || (mapId >= 74 && mapId <= 120) || @@ -1309,8 +1309,8 @@ int Map::getCell(int idx) { _currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT; } - _currentWall = 0x8888; - return _currentWall; + _currentWall._data = 0x8888; + return 0x8888; } _mazeDataIndex = 0; @@ -1324,15 +1324,15 @@ int Map::getCell(int idx) { if (mapId) { // TODO: tile is set to word of (wallLayers >> 8) && 0xff? Makes no sense _currentTile = wallLayers._outdoors._surfaceId; - _currentWall = wallLayers._outdoors._iMiddle; + _currentWall = wallLayers; _currentSurfaceId = wallLayers._outdoors._surfaceId; } else { _currentSurfaceId = SURFTYPE_DEFAULT; - _currentWall = 0; + _currentWall._data = 0; _currentTile = 0; } } else { - if (!mapId) + if (!mapId) return 0; if (pt.x > 31 || pt.y > 31) @@ -1340,11 +1340,11 @@ int Map::getCell(int idx) { else _currentSurfaceId = _mazeData[_mazeDataIndex]._cells[pt.y][pt.x]._surfaceId; - _currentWall = wallLayers._data; - return (_currentWall >> (WALL_NUMBERS[dir][idx * 2] * 4)) & 0xF; + _currentWall = wallLayers; + return (_currentWall._data >> (WALL_NUMBERS[dir][idx * 2] * 4)) & 0xF; } - return _currentWall; + return _currentWall._data; } } // End of namespace Xeen diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 6a061788ac..090619f6d0 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -367,7 +367,7 @@ public: bool _currentIsEvent; bool _currentIsObject; int _currentMonsterFlags; - int _currentWall; + MazeWallLayers _currentWall; int _currentTile; public: Map(XeenEngine *vm); -- cgit v1.2.3 From 747ca9eb2ff87b1205d41fcd0cf65a016ade8e0d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 13 Jan 2015 00:16:26 -0500 Subject: XEEN: Implemented indoor drawing code in draw3d --- engines/xeen/interface.cpp | 158 ++++++++++++++++++++++++++++++++++++++++++--- engines/xeen/interface.h | 10 ++- engines/xeen/module.mk | 1 + engines/xeen/xeen.cpp | 5 +- engines/xeen/xeen.h | 4 +- 5 files changed, 166 insertions(+), 12 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 2dec248d54..7bbe08e378 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -371,6 +371,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); Common::fill(&_wp[0], &_wp[20], 0); Common::fill(&_wo[0], &_wo[308], 0); + Common::fill(&_charsArray1[0], &_charsArray1[12], 0); initDrawStructs(); } @@ -408,6 +409,7 @@ void Interface::setup() { _restoreSprites.load("restorex.icn"); _hpSprites.load("hpbars.icn"); _uiSprites.load("inn.icn"); + _charPowSprites.load("charpow.icn"); // Get mappings to the active characters in the party _vm->_party._activeParty.resize(_vm->_party._partyCount); @@ -855,9 +857,11 @@ void Interface::moveCharacterToRoster() { error("TODO"); } -void Interface::draw3d(bool flag) { +void Interface::draw3d(bool updateFlag) { + Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; + Map &map = *_vm->_map; Screen &screen = *_vm->_screen; -// EventsManager &events = *_vm->_events; if (!screen._windows[11]._enabled) return; @@ -871,15 +875,15 @@ void Interface::draw3d(bool flag) { moveMonsters(); } - MazeObject &objObject = _vm->_map->_mobData._objects[_objNumber]; + MazeObject &objObject = map._mobData._objects[_objNumber]; Direction partyDirection = _vm->_party._mazeDirection; int objNum = _objNumber - 1; // Loop to update the frame numbers for each maze object, applying the animation frame // limits as specified by the map's _animationInfo listing - for (uint i = 0; i < _vm->_map->_mobData._objects.size(); ++i) { - MazeObject &mazeObject = _vm->_map->_mobData._objects[i]; - AnimationEntry &animEntry = _vm->_map->_animationInfo[mazeObject._spriteId]; + for (uint i = 0; i < map._mobData._objects.size(); ++i) { + MazeObject &mazeObject = map._mobData._objects[i]; + AnimationEntry &animEntry = map._animationInfo[mazeObject._spriteId]; int directionIndex = DIRECTION_ANIM_POSITIONS[mazeObject._direction][partyDirection]; if (_isAnimReset) { @@ -899,7 +903,7 @@ void Interface::draw3d(bool flag) { mazeObject._flipped = animEntry._flipped._flags[directionIndex]; } - if (_vm->_map->_isOutdoors) { + if (map._isOutdoors) { error("TODO: draw3d outdoors handling"); } else { // Default all the parts of draw struct not to be drawn by default @@ -931,11 +935,134 @@ void Interface::draw3d(bool flag) { } } } + + setMazeBits(); + _isAnimReset = false; + const int INDOOR_INDEXES[3] = { 157, 151, 154 }; + const int INDOOR_COMBAT_POS[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } }; + const int INDOOR_COMBAT_POS2[4] = { 8, 6, 4, 2 }; + + MazeObject &objObject = map._mobData._objects[_objNumber - 1]; + + for (int idx = 0; idx < 3; ++idx) { + DrawStruct &ds1 = _indoorList[INDOOR_INDEXES[idx]]; + DrawStruct &ds2 = _indoorList[INDOOR_INDEXES[idx] + 1]; + ds1._sprites = nullptr; + ds2._sprites = nullptr; + + if (_charsArray1[idx]) { + int posIndex= combat._attackMon2 && !combat._attackMon3 ? 1 : 0; + --combat._charsArray1[idx]; + + if (combat._monPow[idx]) { + ds1._x = INDOOR_COMBAT_POS[idx][0]; + ds1._frame = 0; + ds1._scale = combat._monsterScale[idx]; + if (ds1._scale == 0x8000) { + ds1._x /= 3; + ds1._y = 60; + } else { + ds1._y = 73; + } + + ds1._flags = SPRFLAG_4000 | SPRFLAG_2000; + ds1._sprites = &_charPowSprites; + } + + if (combat._elemPow[idx]) { + ds2._x = INDOOR_COMBAT_POS[idx][posIndex] + INDOOR_COMBAT_POS2[idx]; + ds2._frame = combat._elemPow[idx]; + ds2._scale = combat._elemScale[idx]; + if (ds2._scale == 0x8000) + ds2._x /= 3; + ds2._flags = SPRFLAG_4000 | SPRFLAG_2000; + ds2._sprites = &_charPowSprites; + } + } + } + + setIndoorsMonsters(); + setIndoorObjects(); + setIndoorWallPics(); + + _indoorList[161]._sprites = nullptr; + _indoorList[160]._sprites = nullptr; + _indoorList[159]._sprites = nullptr; + + // Handle attacking monsters + int monsterIndex = 0; + if (combat._attackMon1 != -1 && map._mobData._monsters[combat._attackMon1]._frame >= 0) { + _indoorList[159] = _indoorList[156]; + _indoorList[160] = _indoorList[157]; + _indoorList[161] = _indoorList[158]; + _indoorList[158]._sprites = nullptr; + _indoorList[156]._sprites = nullptr; + _indoorList[157]._sprites = nullptr; + monsterIndex = 1; + } else if (combat._attackMon2 != -1 && map._mobData._monsters[combat._attackMon2]._frame >= 0) { + _indoorList[159] = _indoorList[150]; + _indoorList[160] = _indoorList[151]; + _indoorList[161] = _indoorList[152]; + _indoorList[152]._sprites = nullptr; + _indoorList[151]._sprites = nullptr; + _indoorList[150]._sprites = nullptr; + monsterIndex = 2; + } else if (combat._attackMon3 != -1 && map._mobData._monsters[combat._attackMon3]._frame >= 0) { + _indoorList[159] = _indoorList[153]; + _indoorList[160] = _indoorList[154]; + _indoorList[161] = _indoorList[155]; + _indoorList[153]._sprites = nullptr; + _indoorList[154]._sprites = nullptr; + _indoorList[155]._sprites = nullptr; + monsterIndex = 3; + } + + drawIndoors(); + + switch (monsterIndex) { + case 1: + _indoorList[156] = _indoorList[159]; + _indoorList[157] = _indoorList[160]; + _indoorList[158] = _indoorList[161]; + break; + case 2: + _indoorList[150] = _indoorList[159]; + _indoorList[151] = _indoorList[160]; + _indoorList[152] = _indoorList[161]; + break; + case 3: + _indoorList[153] = _indoorList[159]; + _indoorList[154] = _indoorList[160]; + _indoorList[155] = _indoorList[161]; + break; + default: + break; + } + } + + animate3d(); + updateAutoMap(); + + if (_vm->_falling == 1) { + error("TODO: Indoor falling"); } - // TODO: more + if (_vm->_falling == 2) { + screen.saveBackground(1); + } + + assembleBorder(); - warning("TODO"); + // TODO: write strings + + if (updateFlag) { + screen._windows[1].update(); + screen._windows[3].update(); + } + + // TODO: more stuff + + events.wait(2); } void Interface::animate3d() { @@ -1124,6 +1251,11 @@ void Interface::setIndoorObjects() { } } +void Interface::setIndoorWallPics() { + // TODO +} + + void Interface::setOutdoorsMonsters() { } @@ -2691,4 +2823,12 @@ void Interface::setMazeBits() { } } +void Interface::drawIndoors() { + // TODO +} + +void Interface::updateAutoMap() { + // TODO +} + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index bd2f2af4b7..ec8a384313 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -81,6 +81,7 @@ private: SpriteResource _hpSprites; SpriteResource _uiSprites; SpriteResource _iconSprites; + SpriteResource _charPowSprites; SpriteResource _charFaces[TOTAL_CHARACTERS]; SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; DrawStruct _faceDrawStructs[4]; @@ -114,6 +115,7 @@ private: byte _wp[20]; byte _wo[308]; bool _thinWall; + int _charsArray1[12]; void loadSprites(); @@ -137,6 +139,10 @@ private: void setIndoorObjects(); + void setIndoorWallPics(); + + void drawIndoors(); + void setOutdoorsMonsters(); void setOutdoorsObjects(); @@ -146,6 +152,8 @@ private: void setMainButtons(); void setMazeBits(); + + void updateAutoMap(); public: Interface(XeenEngine *vm); @@ -157,7 +165,7 @@ public: void loadPartyIcons(); - void draw3d(bool flag); + void draw3d(bool updateFlag); void startup(); diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 076a31a916..2c22322f25 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -4,6 +4,7 @@ MODULE_OBJS := \ clouds\clouds_game.o \ darkside\darkside_game.o \ worldofxeen\worldofxeen_game.o \ + combat.o \ debugger.o \ detection.o \ dialogs.o \ diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 583a1dd262..c749129678 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -36,6 +36,7 @@ namespace Xeen { XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), _randomSource("Xeen") { + _combat = nullptr; _debugger = nullptr; _events = nullptr; _files = nullptr; @@ -50,12 +51,13 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _face1State = 0; _face2State = 0; _noDirectionSense = false; - _falling = false; + _falling = 0; _moveMonsters = false; _mode = MODE_0; } XeenEngine::~XeenEngine() { + delete _combat; delete _debugger; delete _events; delete _interface; @@ -76,6 +78,7 @@ void XeenEngine::initialize() { // Create sub-objects of the engine _files = new FileManager(this); + _combat = new Combat(this); _debugger = new Debugger(this); _events = new EventsManager(this); _interface = new Interface(this); diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index a9b102aec2..59279771d5 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -31,6 +31,7 @@ #include "common/serializer.h" #include "common/util.h" #include "engines/engine.h" +#include "xeen/combat.h" #include "xeen/debugger.h" #include "xeen/dialogs.h" #include "xeen/events.h" @@ -124,6 +125,7 @@ private: virtual Common::Error run(); virtual bool hasFeature(EngineFeature f) const; public: + Combat *_combat; Debugger *_debugger; EventsManager *_events; FileManager *_files; @@ -142,7 +144,7 @@ public: int _face1State; int _face2State; bool _noDirectionSense; - bool _falling; + int _falling; bool _moveMonsters; public: XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); -- cgit v1.2.3 From 1a0a597ff8c02d103d56968bfd18de1908e219d6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 13 Jan 2015 08:51:04 -0500 Subject: XEEN: Add indoor terrain loading and indoor list sprite setting to Map::load --- engines/xeen/interface.cpp | 23 ++++++++++++++++++++++- engines/xeen/interface.h | 16 ++++++++++++++-- engines/xeen/map.cpp | 34 ++++++++++++++++++++++++++++++++++ engines/xeen/map.h | 16 ++++++++++++++++ engines/xeen/resources.cpp | 17 +++++++++++++++++ engines/xeen/resources.h | 6 ++++++ 6 files changed, 109 insertions(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 7bbe08e378..4bf9b1aa3b 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -164,11 +164,28 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2 /*------------------------------------------------------------------------*/ -IndoorDrawList::IndoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]), +IndoorDrawList::IndoorDrawList() : + _sky(_data[1]), _ground(_data[2]), _horizon(_data[28]), + _swl_0F1R(_data[ 46]), _swl_0F1L(_data[44]), _swl_1F1R(_data[134]), + _swl_1F1L(_data[133]), _swl_2F2R(_data[110]), _swl_2F1R(_data[109]), + _swl_2F1L(_data[108]), _swl_2F2L(_data[107]), _swl_3F1R(_data[ 78]), + _swl_3F2R(_data[ 77]), _swl_3F3R(_data[ 76]), _swl_3F4R(_data[ 75]), + _swl_3F1L(_data[ 74]), _swl_3F2L(_data[ 73]), _swl_3F3L(_data[ 72]), + _swl_3F4L(_data[ 71]), _swl_4F4R(_data[ 33]), _swl_4F3R(_data[ 34]), + _swl_4F2R(_data[ 35]), _swl_4F1R(_data[ 36]), _swl_4F1L(_data[ 32]), + _swl_4F2L(_data[ 31]), _swl_4F3L(_data[ 30]), _swl_4F4L(_data[ 29]), + _fwl_4F4R(_data[ 45]), _fwl_4F3R(_data[ 44]), _fwl_4F2R(_data[ 43]), + _fwl_4F1R(_data[ 42]), _fwl_4F( _data[ 41]), _fwl_4F1L(_data[ 40]), + _fwl_4F2L(_data[ 39]), _fwl_4F3L(_data[ 38]), _fwl_4F4L(_data[ 37]), + _fwl_2F1R(_data[121]), _fwl_2F( _data[120]), _fwl_2F1L(_data[119]), + _fwl_3F2R(_data[ 91]), _fwl_3F1R(_data[ 90]), _fwl_3F( _data[ 89]), + _fwl_3F1L(_data[ 88]), _fwl_3F2L(_data[ 87]), _fwl_1F( _data[147]), + _fwl_1F1R(_data[145]), _fwl_1F1L(_data[143]), _objects0(_data[149]), _objects1(_data[125]), _objects2(_data[126]), _objects3(_data[127]), _objects4(_data[97]), _objects5(_data[98]), _objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]), _objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]) { + // Setup draw structure positions _data[0] = DrawStruct(0, 8, 8); _data[1] = DrawStruct(1, 8, 25); _data[2] = DrawStruct(0, 8, 67); @@ -2824,6 +2841,10 @@ void Interface::setMazeBits() { } void Interface::drawIndoors() { + Map &map = *_vm->_map; + + map.getCell(36); + // TODO } diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index ec8a384313..0c014f6032 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -51,8 +51,20 @@ public: class IndoorDrawList { public: DrawStruct _data[170]; - DrawStruct &_skySprite; - DrawStruct &_groundSprite; + DrawStruct &_sky; + DrawStruct &_ground; + DrawStruct &_horizon; + DrawStruct &_swl_0F1R, _swl_0F1L, _swl_1F1R, _swl_1F1L, + _swl_2F2R, _swl_2F1R, _swl_2F1L, _swl_2F2L, + _swl_3F1R, _swl_3F2R, _swl_3F3R, _swl_3F4R, + _swl_3F1L, _swl_3F2L, _swl_3F3L, _swl_3F4L, + _swl_4F4R, _swl_4F3R, _swl_4F2R, _swl_4F1R, + _swl_4F1L, _swl_4F2L, _swl_4F3L, _swl_4F4L; + DrawStruct &_fwl_4F4R, _fwl_4F3R, _fwl_4F2R, _fwl_4F1R, + _fwl_4F, _fwl_4F1L, _fwl_4F2L, _fwl_4F3L, _fwl_4F4L; + DrawStruct &_fwl_2F1R, _fwl_2F, _fwl_2F1L, _fwl_3F2R, + _fwl_3F1R, _fwl_3F, _fwl_3F1L, _fwl_3F2L; + DrawStruct &_fwl_1F, _fwl_1F1R, _fwl_1F1L; DrawStruct &_objects0, _objects1, _objects2, _objects3; DrawStruct &_objects4, _objects5, _objects6, _objects7; DrawStruct &_objects8, _objects9, _objects10, _objects11; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index f9a687b6ee..07cb0d600d 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1050,6 +1050,40 @@ void Map::load(int mapId) { filename = Common::String::format("%03d.pic", _mobData._wallItems[i]._spriteId); _mobData._wallItemSprites[i]._sprites.load(filename); } + + // Handle loading miscellaneous sprites for the map + if (_isOutdoors) { + warning("TODO"); + } else { + warning("TODO"); // Sound loading + + _skySprites.load(isDarkCc ? "sky.sky" : "night.sky"); + _mazeSkySprites.load(Common::String::format("%s.sky", + TERRAIN_TYPES[_mazeData[0]._wallKind])); + _groundSprites.load(Common::String::format("%s.gnd", + TERRAIN_TYPES[_mazeData[0]._wallKind])); + _tileSprites.load(Common::String::format("%s.til", + TERRAIN_TYPES[_mazeData[0]._wallKind])); + + for (int i = 0; i < TOTAL_SURFACES; ++i) { + _surfaceSprites[i].clear(); + + if (_mazeData[0]._surfaceTypes[i] != 0 || i == 4) + _surfaceSprites[i].load(OUTDOOR_SURFACES[i]); + } + + _wallSprites._wal.clear(); + Common::String fwlName = Common::String::format("%s.til", + TERRAIN_TYPES[_mazeData[0]._wallKind]); + _wallSprites._fwl1.load(fwlName); + _wallSprites._fwl2.load(fwlName); + _wallSprites._fwl3.load(fwlName); + _wallSprites._fwl4.load(fwlName); + _wallSprites._swl.load(Common::String::format("s%s.swl", + TERRAIN_TYPES[_mazeData[0]._wallKind])); + + + } } int Map::mazeLookup(const Common::Point &pt, int directionLayerIndex) { diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 090619f6d0..d697243e0d 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -34,6 +34,7 @@ namespace Xeen { #define MAP_WIDTH 16 #define MAP_HEIGHT 16 +#define TOTAL_SURFACES 16 class XeenEngine; @@ -269,6 +270,15 @@ public: MazeWallItem(); }; +struct WallSprites { + SpriteResource _wal; + SpriteResource _fwl1; + SpriteResource _fwl2; + SpriteResource _fwl3; + SpriteResource _fwl4; + SpriteResource _swl; +}; + class Map; class MonsterObjectData { @@ -361,6 +371,12 @@ public: MazeEvents _events; HeadData _headData; AnimationInfo _animationInfo; + SpriteResource _skySprites; + SpriteResource _mazeSkySprites; + SpriteResource _groundSprites; + SpriteResource _tileSprites; + SpriteResource _surfaceSprites[TOTAL_SURFACES]; + WallSprites _wallSprites; bool _currentIsGrate; bool _currentCantRest; bool _currentIsDrain; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 352e59620c..d0f5d6a351 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -66,6 +66,23 @@ const char *const OPTIONS_TITLE = "\v117Copyright (c) 1993 NWC, Inc.\n" "All Rights Reserved\x01"; +const char *const TERRAIN_TYPES[6] = { + "town", "cave", "towr", "cstl", "dung", "scfi" +}; + +const char *const OUTDOOR_WALLS[15] = { + nullptr, "mount", "ltree", "dtree", "grass", "snotree", "snomnt", + "dedltree", "mount", "lavamnt", "palm", "dmount", "dedltree", + "dedltree", "dedltree" +}; + +const char *const OUTDOOR_SURFACES[16] = { + "water.srf", "dirt.srf", "grass.srf", "snow.srf", "swamp.srf", + "lava.srf", "desert.srf", "road.srf", "dwater.srf", "tflr.srf", + "sky.srf", "croad.srf", "sewer.srf", "cloud.srf", "scortch.srf", + "space.srf" +}; + const byte SYMBOLS[20][64] = { { // 0 0x00, 0x00, 0xA8, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x00, 0xA8, 0x9E, 0x9C, 0x9C, 0x9E, 0x9E, 0x9E, diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 2c537fd890..dbb00036ff 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -32,6 +32,12 @@ extern const char *const CREDITS; extern const char *const OPTIONS_TITLE; +extern const char *const TERRAIN_TYPES[6]; + +extern const char *const OUTDOOR_WALLS[15]; + +extern const char *const OUTDOOR_SURFACES[16]; + extern const byte SYMBOLS[20][64]; extern const byte TEXT_COLORS[40][4]; -- cgit v1.2.3 From a856e58ee41505db36e208389d5931952540ca84 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 13 Jan 2015 19:30:03 -0500 Subject: XEEN: Added Combat class and further map loading sprite setting --- engines/xeen/combat.cpp | 37 ++++++++++++++++++ engines/xeen/combat.h | 48 +++++++++++++++++++++++ engines/xeen/interface.h | 5 ++- engines/xeen/map.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++--- engines/xeen/map.h | 2 +- engines/xeen/resources.cpp | 2 +- engines/xeen/resources.h | 2 +- 7 files changed, 180 insertions(+), 10 deletions(-) create mode 100644 engines/xeen/combat.cpp create mode 100644 engines/xeen/combat.h (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp new file mode 100644 index 0000000000..f870083e6f --- /dev/null +++ b/engines/xeen/combat.cpp @@ -0,0 +1,37 @@ +/* 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 "xeen/combat.h" +#include "common/algorithm.h" + +namespace Xeen { + +Combat::Combat(XeenEngine *vm): _vm(vm) { + _attackMon1 = _attackMon2 = _attackMon3 = 0; + Common::fill(&_charsArray1[0], &_charsArray1[12], 0); + Common::fill(&_monPow[0], &_monPow[12], 0); + Common::fill(&_monsterScale[0], &_monsterScale[12], 0); + Common::fill(&_elemPow[0], &_elemPow[12], 0); + Common::fill(&_elemScale[0], &_elemScale[12], 0); +} + +} // End of namespace Xeen diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h new file mode 100644 index 0000000000..3360bbdddf --- /dev/null +++ b/engines/xeen/combat.h @@ -0,0 +1,48 @@ +/* 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 XEEN_COMBAT_H +#define XEEN_COMBAT_H + +#include "common/scummsys.h" + +namespace Xeen { + +class XeenEngine; + +class Combat { +private: + XeenEngine *_vm; +public: + int _charsArray1[12]; + bool _monPow[12]; + int _monsterScale[12]; + int _elemPow[12]; + int _elemScale[12]; + int _attackMon1, _attackMon2, _attackMon3; +public: + Combat(XeenEngine *vm); +}; + +} // End of namespace Xeen + +#endif /* XEEN_COMBAT_H */ diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 0c014f6032..498de3c195 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -98,8 +98,6 @@ private: SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; DrawStruct _faceDrawStructs[4]; DrawStruct _mainList[16]; - OutdoorDrawList _outdoorList; - IndoorDrawList _indoorList; int _combatCharIds[8]; int _batUIFrame; @@ -166,6 +164,9 @@ private: void setMazeBits(); void updateAutoMap(); +public: + OutdoorDrawList _outdoorList; + IndoorDrawList _indoorList; public: Interface(XeenEngine *vm); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 07cb0d600d..1a01b441f6 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -22,6 +22,7 @@ #include "common/serializer.h" #include "xeen/map.h" +#include "xeen/interface.h" #include "xeen/resources.h" #include "xeen/saves.h" #include "xeen/screen.h" @@ -866,6 +867,9 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { void Map::load(int mapId) { Screen &screen = *_vm->_screen; + IndoorDrawList &indoorList = _vm->_interface->_indoorList; + OutdoorDrawList &outdoorList = _vm->_interface->_outdoorList; + if (_vm->_falling) { Window &w = screen._windows[9]; w.open(); @@ -1010,8 +1014,9 @@ void Map::load(int mapId) { // TODO: Switch setting flags that don't seem to ever be used // Reload the monster data for the main maze that we're loading + mapId = _vm->_party._mazeId; Common::String filename = Common::String::format("maze%c%03d.mob", - (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); + (mapId >= 100) ? 'x' : '0', mapId); File mobFile(filename, *_vm->_saves); XeenSerializer sMob(&mobFile, nullptr); _mobData.synchronize(sMob, _monsterData); @@ -1020,9 +1025,9 @@ void Map::load(int mapId) { // Load sprites for the objects for (uint i = 0; i < _mobData._objectSprites.size(); ++i) { if (_vm->_party._cloudsEnd && _mobData._objectSprites[i]._spriteId == 85 && - _vm->_party._mazeId == 27 && isDarkCc) { + mapId == 27 && isDarkCc) { // TODO: Flags set that don't seem to be used - } else if (_vm->_party._mazeId == 12 && _vm->_party._gameFlags[43] && + } else if (mapId == 12 && _vm->_party._gameFlags[43] && _mobData._objectSprites[i]._spriteId == 118 && !isDarkCc) { filename = "085.obj"; _mobData._objectSprites[0]._spriteId = 85; @@ -1053,7 +1058,25 @@ void Map::load(int mapId) { // Handle loading miscellaneous sprites for the map if (_isOutdoors) { - warning("TODO"); + warning("TODO"); // Sound loading + + _skySprites.load(isDarkCc ? "sky.sky" : "night.sky"); + _groundSprites.load("water.out"); + _tileSprites.load("outdoor.til"); + outdoorList._skySprite._sprites = &_skySprites; + outdoorList._groundSprite._sprites = &_groundSprites; + + for (int i = 0; i < TOTAL_SURFACES; ++i) { + _wallSprites._surfaces[i].clear(); + if (_mazeData[0]._wallTypes[i] != 0) { + _wallSprites._surfaces[i].load(Common::String::format("%s.wal", + SURFACE_TYPE_NAMES[i])); + } + + _surfaceSprites[i].clear(); + if (i != 0 && _mazeData[0]._wallTypes[i] != 0) + _surfaceSprites[i].load(OUTDOOR_SURFACES[_mazeData[0]._surfaceTypes[i]]); + } } else { warning("TODO"); // Sound loading @@ -1072,7 +1095,7 @@ void Map::load(int mapId) { _surfaceSprites[i].load(OUTDOOR_SURFACES[i]); } - _wallSprites._wal.clear(); + _wallSprites._surfaces[0].clear(); Common::String fwlName = Common::String::format("%s.til", TERRAIN_TYPES[_mazeData[0]._wallKind]); _wallSprites._fwl1.load(fwlName); @@ -1082,7 +1105,68 @@ void Map::load(int mapId) { _wallSprites._swl.load(Common::String::format("s%s.swl", TERRAIN_TYPES[_mazeData[0]._wallKind])); + // Set entries in the indoor draw list to the correct sprites + // for drawing various parts of the background + indoorList._swl_0F1R._sprites = &_wallSprites._swl; + indoorList._swl_0F1L._sprites = &_wallSprites._swl; + indoorList._swl_1F1R._sprites = &_wallSprites._swl; + indoorList._swl_1F1L._sprites = &_wallSprites._swl; + indoorList._swl_2F2R._sprites = &_wallSprites._swl; + indoorList._swl_2F1R._sprites = &_wallSprites._swl; + indoorList._swl_2F1L._sprites = &_wallSprites._swl; + indoorList._swl_2F2L._sprites = &_wallSprites._swl; + + indoorList._swl_3F1R._sprites = &_wallSprites._swl; + indoorList._swl_3F2R._sprites = &_wallSprites._swl; + indoorList._swl_3F3R._sprites = &_wallSprites._swl; + indoorList._swl_3F4R._sprites = &_wallSprites._swl; + indoorList._swl_3F1L._sprites = &_wallSprites._swl; + indoorList._swl_3F2L._sprites = &_wallSprites._swl; + indoorList._swl_3F3L._sprites = &_wallSprites._swl; + indoorList._swl_3F4L._sprites = &_wallSprites._swl; + + indoorList._swl_4F4R._sprites = &_wallSprites._swl; + indoorList._swl_4F3R._sprites = &_wallSprites._swl; + indoorList._swl_4F2R._sprites = &_wallSprites._swl; + indoorList._swl_4F1R._sprites = &_wallSprites._swl; + indoorList._swl_4F1L._sprites = &_wallSprites._swl; + indoorList._swl_4F2L._sprites = &_wallSprites._swl; + indoorList._swl_4F3L._sprites = &_wallSprites._swl; + indoorList._swl_4F4L._sprites = &_wallSprites._swl; + + indoorList._fwl_4F4R._sprites = &_wallSprites._fwl4; + indoorList._fwl_4F3R._sprites = &_wallSprites._fwl4; + indoorList._fwl_4F2R._sprites = &_wallSprites._fwl4; + indoorList._fwl_4F1R._sprites = &_wallSprites._fwl4; + indoorList._fwl_4F._sprites = &_wallSprites._fwl4; + indoorList._fwl_4F1L._sprites = &_wallSprites._fwl4; + indoorList._fwl_4F2L._sprites = &_wallSprites._fwl4; + indoorList._fwl_4F3L._sprites = &_wallSprites._fwl4; + indoorList._fwl_4F4L._sprites = &_wallSprites._fwl4; + + indoorList._fwl_2F1R._sprites = &_wallSprites._fwl3; + indoorList._fwl_2F._sprites = &_wallSprites._fwl3; + indoorList._fwl_2F1L._sprites = &_wallSprites._fwl3; + indoorList._fwl_3F2R._sprites = &_wallSprites._fwl3; + indoorList._fwl_3F1R._sprites = &_wallSprites._fwl3; + indoorList._fwl_3F._sprites = &_wallSprites._fwl3; + indoorList._fwl_3F1L._sprites = &_wallSprites._fwl3; + indoorList._fwl_3F2L._sprites = &_wallSprites._fwl3; + + indoorList._fwl_1F._sprites = &_wallSprites._fwl1; + indoorList._fwl_1F1R._sprites = &_wallSprites._fwl1; + indoorList._fwl_1F1L._sprites = &_wallSprites._fwl1; + + indoorList._horizon._sprites = &_groundSprites; + // Down show horizon for certain maps + if (_vm->_files->_isDarkCc) { + if ((mapId >= 89 && mapId <= 112) || mapId == 128 || mapId == 129) + indoorList._horizon._sprites = nullptr; + } else { + if (mapId >= 25 && mapId <= 27) + indoorList._horizon._sprites = nullptr; + } } } diff --git a/engines/xeen/map.h b/engines/xeen/map.h index d697243e0d..37eba7074c 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -271,7 +271,7 @@ public: }; struct WallSprites { - SpriteResource _wal; + SpriteResource _surfaces[TOTAL_SURFACES]; SpriteResource _fwl1; SpriteResource _fwl2; SpriteResource _fwl3; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index d0f5d6a351..5740a419bd 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -70,7 +70,7 @@ const char *const TERRAIN_TYPES[6] = { "town", "cave", "towr", "cstl", "dung", "scfi" }; -const char *const OUTDOOR_WALLS[15] = { +const char *const SURFACE_TYPE_NAMES[15] = { nullptr, "mount", "ltree", "dtree", "grass", "snotree", "snomnt", "dedltree", "mount", "lavamnt", "palm", "dmount", "dedltree", "dedltree", "dedltree" diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index dbb00036ff..71ac91f641 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -34,7 +34,7 @@ extern const char *const OPTIONS_TITLE; extern const char *const TERRAIN_TYPES[6]; -extern const char *const OUTDOOR_WALLS[15]; +extern const char *const SURFACE_TYPE_NAMES[15]; extern const char *const OUTDOOR_SURFACES[16]; -- cgit v1.2.3 From 2b78d5190b6b734fbf24ab533cef0c8f427cbe0f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 14 Jan 2015 00:20:45 -0500 Subject: XEEN: Implementing drawIndoors --- engines/xeen/interface.cpp | 896 ++++++++++++++++++++++++++++++++++++++++++++- engines/xeen/interface.h | 3 +- engines/xeen/map.cpp | 4 +- engines/xeen/map.h | 5 +- engines/xeen/resources.cpp | 14 + engines/xeen/resources.h | 4 + 6 files changed, 920 insertions(+), 6 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 4bf9b1aa3b..12317da0ef 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -377,6 +377,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { _hiliteChar = -1; _intrIndex1 = 0; _flipWtr = false; + _flipWall = false; _flag1 = false; _animCounter = 0; _isAnimReset = false; @@ -384,11 +385,11 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { _tillMove = 0; _objNumber = 0; _thinWall = false; + _overallFrame = 0; Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); Common::fill(&_wp[0], &_wp[20], 0); Common::fill(&_wo[0], &_wo[308], 0); - Common::fill(&_charsArray1[0], &_charsArray1[12], 0); initDrawStructs(); } @@ -967,7 +968,7 @@ void Interface::draw3d(bool updateFlag) { ds1._sprites = nullptr; ds2._sprites = nullptr; - if (_charsArray1[idx]) { + if (combat._charsArray1[idx]) { int posIndex= combat._attackMon2 && !combat._attackMon3 ? 1 : 0; --combat._charsArray1[idx]; @@ -2842,8 +2843,897 @@ void Interface::setMazeBits() { void Interface::drawIndoors() { Map &map = *_vm->_map; + int surfaceId; + int idx; - map.getCell(36); + for (int cellIndex = 0; cellIndex < 25; ++cellIndex) { + map.getCell(DRAW_NUMBERS[cellIndex]); + + DrawStruct &drawStruct = _indoorList[3 + cellIndex]; + drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId]; + + surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; + if (surfaceId == 5 || surfaceId == 12) { + drawStruct._flags = _flipWtr; + drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWtr ? 1 : 0]; + } + else { + drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWall ? 1 : 0]; + drawStruct._flags = _flipWall ? 0 : SPRFLAG_HORIZ_FLIPPED; + } + } + + if (!_wo[27] && !_wo[20] && !_wo[23] && !_wo[12] && !_wo[8] && !_wo[30]) { + if (_wo[39]) + _indoorList._swl_4F4L._frame = 22; + else if (_wo[83]) + _indoorList._swl_4F4L._frame = 46; + } + + if (!_wo[27] && !_wo[22] && !_wo[17] && !_wo[12] && !_wo[8]) { + if (_wo[38]) + _indoorList._swl_4F3L._frame = 20; + else if (_wo[82]) + _indoorList._swl_4F3L._frame = 44; + } + + if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[2] && !_wo[7]) { + if (_wo[37]) + _indoorList._swl_4F2L._frame = 18; + else if (_wo[81]) + _indoorList._swl_4F2L._frame = 42; + } + + if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[6]) { + if (_wo[36]) + _indoorList._swl_4F1L._frame = 16; + else if (_wo[80]) + _indoorList._swl_4F1L._frame = 40; + } + + if (!_wo[27] && !_wo[21] && !_wo[24] && !_wo[14] && !_wo[10] && !_wo[31]) { + if (_wo[43]) + _indoorList._swl_4F4R._frame = 23; + else if (_wo[87]) + _indoorList._swl_4F4R._frame = 47; + } + + if (!_wo[27] && !_wo[22] && !_wo[19] && !_wo[14] && !_wo[10]) { + if (_wo[42]) + _indoorList._swl_4F3R._frame = 21; + else if (_wo[86]) + _indoorList._swl_4F3R._frame = 45; + } + + if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[5] && !_wo[9]) { + if (_wo[41]) + _indoorList._swl_4F2R._frame = 19; + else if (_wo[85]) + _indoorList._swl_4F2R._frame = 43; + } + + if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[6]) { + if (_wo[40]) + _indoorList._swl_4F1R._frame = 17; + else if (_wo[84]) + _indoorList._swl_4F1R._frame = 41; + } + + if (!_wo[25] && !_wo[28] && !_wo[20] && !_wo[11] && + !_wo[16] && !_wo[30] && !_wo[32]) { + if (_wo[88]) + _indoorList._fwl_4F4L._frame = 7; + else if (_wo[78]) + _indoorList._fwl_4F4L._frame = 16; + else if (_wo[148]) + _indoorList._fwl_4F4L._frame = _overallFrame + 1; + else if (_wo[108]) + _indoorList._fwl_4F4L._frame = 8; + else if (_wo[168]) + _indoorList._fwl_4F4L._frame = 10; + else if (_wo[128]) + _indoorList._fwl_4F4L._frame = 9; + else if (_wo[34]) + _indoorList._fwl_4F4L._frame = 0; + else if (_wo[188]) + _indoorList._fwl_4F4L._frame = 15; + else if (_wo[208]) + _indoorList._fwl_4F4L._frame = 14; + else if (_wo[228]) + _indoorList._fwl_4F4L._frame = 6; + else if (_wo[248]) + _indoorList._fwl_4F4L._frame = 11; + else if (_wo[268]) + _indoorList._fwl_4F4L._frame = 12; + else if (_wo[288]) + _indoorList._fwl_4F4L._frame = 13; + } + + if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31] && !_wo[33]) { + if (_wo[93]) + _indoorList._fwl_4F4R._frame = 7; + else if (_wo[79]) + _indoorList._fwl_4F4R._frame = 16; + else if (_wo[153]) + _indoorList._fwl_4F4R._frame = _overallFrame + 1; + else if (_wo[113]) + _indoorList._fwl_4F4R._frame = 8; + else if (_wo[173]) + _indoorList._fwl_4F4R._frame = 10; + else if (_wo[133]) + _indoorList._fwl_4F4R._frame = 9; + else if (_wo[35]) + _indoorList._fwl_4F4R._frame = 0; + else if (_wo[79]) + _indoorList._fwl_4F4R._frame = 15; + else if (_wo[213]) + _indoorList._fwl_4F4R._frame = 14; + else if (_wo[233]) + _indoorList._fwl_4F4R._frame = 6; + else if (_wo[253]) + _indoorList._fwl_4F4R._frame = 11; + else if (_wo[273]) + _indoorList._fwl_4F4R._frame = 12; + else if (_wo[293]) + _indoorList._fwl_4F4R._frame = 13; + } + + if (!_wo[25] && !_wo[28] && !_wo[20] && !_wo[11] && !_wo[16] && !_wo[30]) { + if (_wo[32]) + _indoorList._swl_3F4L._frame = 14; + else if (_wo[76]) + _indoorList._swl_3F4L._frame = 38; + } + + if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31]) { + if (_wo[33]) + _indoorList._fwl_3F1R._frame = 15; + else if (_wo[77]) + _indoorList._swl_3F1R._frame = 39; + } + + if (_wo[28] && _wo[27]) { + } + else if (_wo[28] && _wo[12]) { + } + else if (_wo[28] && _wo[23]) { + } + else if (_wo[28] && _wo[8]) { + } + else if (_wo[25] && _wo[27]) { + } + else if (_wo[25] && _wo[12]) { + } + else if (_wo[25] && _wo[23]) { + } + else if (_wo[25] && _wo[8]) { + } + else if (_wo[11] && _wo[27]) { + } + else if (_wo[11] && _wo[12]) { + } + else if (_wo[11] && _wo[23]) { + } + else if (_wo[11] && _wo[8]) { + } + else if (_wo[17] && _wo[27]) { + } + else if (_wo[17] && _wo[12]) { + } + else if (_wo[17] && _wo[23]) { + } + else if (_wo[17] && _wo[8]) { + } + else if (_wo[20]) { + } + else if (_wo[30]) { + _indoorList._swl_3F3L._frame = 12; + } + else if (_wo[74]) { + _indoorList._swl_3F3L._frame = 36; + } + + if (_wo[29] && _wo[27]) { + } + else if (_wo[29] && _wo[14]) { + } + else if (_wo[29] && _wo[24]) { + } + else if (_wo[29] && _wo[10]) { + } + else if (_wo[26] && _wo[27]) { + } + else if (_wo[26] && _wo[14]) { + } + else if (_wo[26] && _wo[24]) { + } + else if (_wo[26] && _wo[10]) { + } + else if (_wo[13] && _wo[27]) { + } + else if (_wo[13] && _wo[14]) { + } + else if (_wo[13] && _wo[24]) { + } + else if (_wo[13] && _wo[10]) { + } + else if (_wo[19] && _wo[27]) { + } + else if (_wo[19] && _wo[24]) { + } + else if (_wo[19] && _wo[10]) { + } + else if (_wo[21]) { + } + else if (_wo[31]) { + _indoorList._swl_3F2R._frame = 13; + } + else if (_wo[75]) { + _indoorList._swl_3F2R._frame = 37; + } + + if (!_wo[27] && !_wo[20] && !_wo[12] && !_wo[23] && !_wo[8] && !_wo[30]) { + if (_wo[89]) + _indoorList._fwl_4F3L._frame = 7; + else if (_wo[44]) + _indoorList._fwl_4F3L._frame = 16; + else if (_wo[149]) + _indoorList._fwl_4F3L._frame = _overallFrame + 1; + else if (_wo[109]) + _indoorList._fwl_4F3L._frame = 8; + else if (_wo[169]) + _indoorList._fwl_4F3L._frame = 10; + else if (_wo[129]) + _indoorList._fwl_4F3L._frame = 9; + else if (_wo[0]) + _indoorList._fwl_4F3L._frame = 0; + else if (_wo[189]) + _indoorList._fwl_4F3L._frame = 15; + else if (_wo[209]) + _indoorList._fwl_4F3L._frame = 14; + else if (_wo[229]) + _indoorList._fwl_4F3L._frame = 6; + else if (_wo[249]) + _indoorList._fwl_4F3L._frame = 11; + else if (_wo[269]) + _indoorList._fwl_4F3L._frame = 12; + else if (_wo[289]) + _indoorList._fwl_4F3L._frame = 13; + } + + if (_wo[22] && _wo[20]) { + } + else if (_wo[22] && _wo[23]) { + } + else if (_wo[20] && _wo[17]) { + } + else if (_wo[23] && _wo[17]) { + } + else if (_wo[12]) { + } + else if (_wo[8]) { + } + else if (_wo[90]) { + _indoorList._fwl_4F2L._frame = 7; + } + else if (_wo[45]) { + _indoorList._fwl_4F2L._frame = 16; + } + else if (_wo[150]) { + _indoorList._fwl_4F2L._frame = _overallFrame + 1; + } + else if (_wo[110]) { + _indoorList._fwl_4F2L._frame = 8; + } + else if (_wo[170]) { + _indoorList._fwl_4F2L._frame = 10; + } + else if (_wo[130]) { + _indoorList._fwl_4F2L._frame = 9; + } + else if (_wo[1]) { + _indoorList._fwl_4F2L._frame = 0; + } + else if (_wo[190]) { + _indoorList._fwl_4F2L._frame = 15; + } + else if (_wo[210]) { + _indoorList._fwl_4F2L._frame = 14; + } + else if (_wo[230]) { + _indoorList._fwl_4F2L._frame = 6; + } + else if (_wo[250]) { + _indoorList._fwl_4F2L._frame = 11; + } + else if (_wo[270]) { + _indoorList._fwl_4F2L._frame = 12; + } + else if (_wo[290]) { + _indoorList._fwl_4F2L._frame = 13; + } + + if (_wo[15] && _wo[17]) { + } + else if (_wo[15] && _wo[12]) { + } + else if (_wo[12] && _wo[7]) { + } + else if (_wo[17] && _wo[7]) { + } + else if (_wo[91]) { + _indoorList._fwl_4F1L._frame = 7; + } + else if (_wo[46]) { + _indoorList._fwl_4F1L._frame = 16; + } + else if (_wo[151]) { + _indoorList._fwl_4F1L._frame = _overallFrame + 1; + } + else if (_wo[111]) { + _indoorList._fwl_4F1L._frame = 8; + } + else if (_wo[171]) { + _indoorList._fwl_4F1L._frame = 10; + } + else if (_wo[131]) { + _indoorList._fwl_4F1L._frame = 9; + } + else if (_wo[2]) { + _indoorList._fwl_4F1L._frame = 0; + } + else if (_wo[191]) { + _indoorList._fwl_4F1L._frame = 15; + } + else if (_wo[211]) { + _indoorList._fwl_4F1L._frame = 14; + } + else if (_wo[231]) { + _indoorList._fwl_4F1L._frame = 6; + } + else if (_wo[251]) { + _indoorList._fwl_4F1L._frame = 11; + } + else if (_wo[271]) { + _indoorList._fwl_4F1L._frame = 12; + } + else if (_wo[291]) { + _indoorList._fwl_4F1L._frame = 13; + } + + if (!_wo[27] && !_wo[21] && !_wo[14] && !_wo[24] && !_wo[10] && !_wo[31]) { + if (_wo[92]) { + _indoorList._fwl_4F3R._frame = 7; + } + else if (_wo[47]) { + _indoorList._fwl_4F3R._frame = 16; + } + else if (_wo[152]) { + _indoorList._fwl_4F3R._frame = _overallFrame + 1; + } + else if (_wo[112]) { + _indoorList._fwl_4F3R._frame = 8; + } + else if (_wo[172]) { + _indoorList._fwl_4F3R._frame = 10; + } + else if (_wo[132]) { + _indoorList._fwl_4F3R._frame = 9; + } + else if (_wo[3]) { + _indoorList._fwl_4F3R._frame = 0; + } + else if (_wo[192]) { + _indoorList._fwl_4F3R._frame = 15; + } + else if (_wo[212]) { + _indoorList._fwl_4F3R._frame = 14; + } + else if (_wo[232]) { + _indoorList._fwl_4F3R._frame = 6; + } + else if (_wo[252]) { + _indoorList._fwl_4F3R._frame = 11; + } + else if (_wo[272]) { + _indoorList._fwl_4F3R._frame = 12; + } + else if (_wo[292]) { + _indoorList._fwl_4F3R._frame = 13; + } + } + + if (_wo[22] && _wo[21]) { + } + else if (_wo[22] && _wo[24]) { + } + else if (_wo[21] && _wo[19]) { + } + else if (_wo[24] && _wo[19]) { + } + else if (_wo[14] || _wo[10]) { + } + else if (_wo[94]) { + _indoorList._fwl_4F2R._frame = 7; + } + else if (_wo[48]) { + _indoorList._fwl_4F2R._frame = 16; + } + else if (_wo[154]) { + _indoorList._fwl_4F2R._frame = _overallFrame + 1; + } + else if (_wo[114]) { + _indoorList._fwl_4F2R._frame = 8; + } + else if (_wo[174]) { + _indoorList._fwl_4F2R._frame = 10; + } + else if (_wo[134]) { + _indoorList._fwl_4F2R._frame = 9; + } + else if (_wo[4]) { + _indoorList._fwl_4F2R._frame = 0; + } + else if (_wo[194]) { + _indoorList._fwl_4F2R._frame = 15; + } + else if (_wo[214]) { + _indoorList._fwl_4F2R._frame = 14; + } + else if (_wo[234]) { + _indoorList._fwl_4F2R._frame = 6; + } + else if (_wo[254]) { + _indoorList._fwl_4F2R._frame = 11; + } + else if (_wo[274]) { + _indoorList._fwl_4F2R._frame = 12; + } + else if (_wo[294]) { + _indoorList._fwl_4F2R._frame = 13; + } + + if (_wo[15] && _wo[19]) { + } + else if (_wo[15] && _wo[14]) { + } + else if (_wo[14] && _wo[9]) { + } + else if (_wo[19] && _wo[9]) { + } + else if (_wo[95]) { + _indoorList._fwl_4F1R._frame = 7; + } + else if (_wo[49]) { + _indoorList._fwl_4F1R._frame = 16; + } + else if (_wo[155]) { + _indoorList._fwl_4F1R._frame = _overallFrame + 1; + } + else if (_wo[115]) { + _indoorList._fwl_4F1R._frame = 8; + } + else if (_wo[175]) { + _indoorList._fwl_4F1R._frame = 10; + } + else if (_wo[135]) { + _indoorList._fwl_4F1R._frame = 9; + } + else if (_wo[5]) { + _indoorList._fwl_4F1R._frame = 0; + } + else if (_wo[195]) { + _indoorList._fwl_4F1R._frame = 15; + } + else if (_wo[215]) { + _indoorList._fwl_4F1R._frame = 14; + } + else if (_wo[235]) { + _indoorList._fwl_4F1R._frame = 6; + } + else if (_wo[255]) { + _indoorList._fwl_4F1R._frame = 11; + } + else if (_wo[275]) { + _indoorList._fwl_4F1R._frame = 12; + } + else if (_wo[295]) { + _indoorList._fwl_4F1R._frame = 13; + } + + if (_wo[27] || _wo[22] || _wo[15] || _wo[96]) { + } + else if (_wo[50]) { + _indoorList._fwl_4F._frame = 16; + } + else if (_wo[156]) { + _indoorList._fwl_4F._frame = _overallFrame + 1; + } + else if (_wo[116]) { + _indoorList._fwl_4F._frame = 8; + } + else if (_wo[176]) { + _indoorList._fwl_4F._frame = 10; + } + else if (_wo[136]) { + _indoorList._fwl_4F._frame = 9; + } + else if (_wo[6]) { + _indoorList._fwl_4F._frame = 0; + } + else if (_wo[196]) { + _indoorList._fwl_4F._frame = 15; + } + else if (_wo[216]) { + _indoorList._fwl_4F._frame = 14; + } + else if (_wo[236]) { + _indoorList._fwl_4F._frame = 6; + } + else if (_wo[256]) { + _indoorList._fwl_4F._frame = 11; + } + else if (_wo[276]) { + _indoorList._fwl_4F._frame = 12; + } + else if (_wo[296]) { + _indoorList._fwl_4F._frame = 13; + } + + if (!_wo[27] && !_wo[22] && !_wo[15]) { + if (_wo[7]) + _indoorList._swl_3F1L._frame = 8; + else if (_wo[51]) + _indoorList._swl_3F1L._frame = 32; + } + + if (_wo[22] && _wo[23]) { + } + else if (_wo[22] && _wo[20]) { + } + else if (_wo[17] && _wo[23]) { + } + else if (_wo[17] && _wo[20]) { + } + else if (_wo[8]) { + _indoorList._swl_3F2L._frame = 10; + } + else if (_wo[52]) { + _indoorList._swl_3F2L._frame = 34; + } + + if (_wo[27] || _wo[22] || _wo[15]) { + } + else if (_wo[9]) { + _indoorList._swl_3F4R._frame = 9; + } + else if (_wo[53]) { + _indoorList._swl_3F4R._frame = 33; + } + + if (_wo[22] && _wo[24]) { + } + else if (_wo[22] && _wo[21]) { + } + else if (_wo[19] && _wo[24]) { + } + else if (_wo[19] && _wo[21]) { + } + else if (_wo[14]) { + } + else if (_wo[10]) { + _indoorList._swl_3F3R._frame = 11; + } + else if (_wo[54]) { + _indoorList._swl_3F3R._frame = 35; + } + + if (_wo[25] || _wo[28] || _wo[20] || _wo[16]) { + } + else if (_wo[97]) { + _indoorList._fwl_3F2L._frame = 24; + } + else if (_wo[55]) { + _indoorList._fwl_3F2L._frame = 33; + } + else if (_wo[137]) { + _indoorList._fwl_3F2L._frame = 26; + } + else if (_wo[157]) { + _indoorList._fwl_3F2L._frame = _overallFrame + 18; + } + else if (_wo[117]) { + _indoorList._fwl_3F2L._frame = 25; + } + else if (_wo[177]) { + _indoorList._fwl_3F2L._frame = 27; + } + else if (_wo[11]) { + _indoorList._fwl_3F2L._frame = 17; + } + else if (_wo[197]) { + _indoorList._fwl_3F2L._frame = 32; + } + else if (_wo[217]) { + _indoorList._fwl_3F2L._frame = 31; + } + else if (_wo[237]) { + _indoorList._fwl_3F2L._frame = 23; + } + else if (_wo[257]) { + _indoorList._fwl_3F2L._frame = 28; + } + else if (_wo[277]) { + _indoorList._fwl_3F2L._frame = 29; + } + else if (_wo[297]) { + _indoorList._fwl_3F2L._frame = 30; + } + + if (_wo[22] && _wo[23]) { + } + else if (_wo[22] && _wo[20]) { + } + else if (_wo[23] && _wo[17]) { + } + else if (_wo[20] && _wo[17]) { + } + else if (_wo[98]) { + _indoorList._fwl_3F1L._frame = 24; + } + else if (_wo[56]) { + _indoorList._fwl_3F1L._frame = 33; + } + else if (_wo[178]) { + _indoorList._fwl_3F1L._frame = 27; + } + else if (_wo[118]) { + _indoorList._fwl_3F1L._frame = 25; + } + else if (_wo[158]) { + _indoorList._fwl_3F1L._frame = _overallFrame + 18; + } + else if (_wo[138]) { + _indoorList._fwl_3F1L._frame = 26; + } + else if (_wo[12]) { + _indoorList._fwl_3F1L._frame = 17; + } + else if (_wo[198]) { + _indoorList._fwl_3F1L._frame = 32; + } + else if (_wo[218]) { + _indoorList._fwl_3F1L._frame = 31; + } + else if (_wo[238]) { + _indoorList._fwl_3F1L._frame = 23; + } + else if (_wo[258]) { + _indoorList._fwl_3F1L._frame = 28; + } + else if (_wo[278]) { + _indoorList._fwl_3F1L._frame = 29; + } + else if (_wo[298]) { + _indoorList._fwl_3F1L._frame = 30; + } + + if (_wo[26] || _wo[29] || _wo[21] || _wo[18]) { + } + else if (_wo[99]) { + _indoorList._fwl_3F2R._frame = 24; + } + else if (_wo[57]) { + _indoorList._fwl_3F2R._frame = 33; + } + else if (_wo[139]) { + _indoorList._fwl_3F2R._frame = 26; + } + else if (_wo[159]) { + _indoorList._fwl_3F2R._frame = _overallFrame + 18; + } + else if (_wo[119]) { + _indoorList._fwl_3F2R._frame = 25; + } + else if (_wo[179]) { + _indoorList._fwl_3F2R._frame = 27; + } + else if (_wo[13]) { + _indoorList._fwl_3F2R._frame = 17; + } + else if (_wo[199]) { + _indoorList._fwl_3F2R._frame = 32; + } + else if (_wo[219]) { + _indoorList._fwl_3F2R._frame = 31; + } + else if (_wo[239]) { + _indoorList._fwl_3F2R._frame = 23; + } + else if (_wo[259]) { + _indoorList._fwl_3F2R._frame = 28; + } + else if (_wo[279]) { + _indoorList._fwl_3F2R._frame = 29; + } + else if (_wo[299]) { + _indoorList._fwl_3F2R._frame = 30; + } + + if (_wo[22] && _wo[24]) { + } + else if (_wo[22] && _wo[21]) { + } + else if (_wo[24] && _wo[19]) { + } + else if (_wo[21] && _wo[19]) { + } + else if (_wo[100]) { + _indoorList._fwl_3F1R._frame = 24; + } + else if (_wo[58]) { + _indoorList._fwl_3F1R._frame = 33; + } + else if (_wo[140]) { + _indoorList._fwl_3F1R._frame = 26; + } + else if (_wo[160]) { + _indoorList._fwl_3F1R._frame = _overallFrame + 18; + } + else if (_wo[120]) { + _indoorList._fwl_3F1R._frame = 25; + } + else if (_wo[180]) { + _indoorList._fwl_3F1R._frame = 27; + } + else if (_wo[14]) { + _indoorList._fwl_3F1R._frame = 17; + } + else if (_wo[200]) { + _indoorList._fwl_3F1R._frame = 32; + } + else if (_wo[220]) { + _indoorList._fwl_3F1R._frame = 31; + } + else if (_wo[240]) { + _indoorList._fwl_3F1R._frame = 23; + } + else if (_wo[260]) { + _indoorList._fwl_3F1R._frame = 28; + } + else if (_wo[280]) { + _indoorList._fwl_3F1R._frame = 29; + } + else if (_wo[300]) { + _indoorList._fwl_3F1R._frame = 30; + } + + if (_wo[22] || _wo[27]) { + } + else if (_wo[101]) { + _indoorList._fwl_3F._frame = 24; + } + else if (_wo[59]) { + _indoorList._fwl_3F._frame = 33; + } + else if (_wo[141]) { + _indoorList._fwl_3F._frame = 26; + } + else if (_wo[161]) { + _indoorList._fwl_3F._frame = _overallFrame + 18; + } + else if (_wo[121]) { + _indoorList._fwl_3F._frame = 25; + } + else if (_wo[181]) { + _indoorList._fwl_3F._frame = 27; + } + else if (_wo[15]) { + _indoorList._fwl_3F._frame = 17; + } + else if (_wo[201]) { + _indoorList._fwl_3F._frame = 32; + } + else if (_wo[221]) { + _indoorList._fwl_3F._frame = 31; + } + else if (_wo[241]) { + _indoorList._fwl_3F._frame = 23; + } + else if (_wo[261]) { + _indoorList._fwl_3F._frame = 28; + } + else if (_wo[281]) { + _indoorList._fwl_3F._frame = 29; + } + else if (_wo[301]) { + _indoorList._fwl_3F._frame = 30; + } + + if (_wo[25] || _wo[28] || _wo[20]) { + } + else if (_wo[16]) { + _indoorList._swl_2F2L._frame = 6; + } + else if (_wo[60]) { + _indoorList._swl_2F2L._frame = 30; + } + + if (_wo[27] || _wo[22]) { + } + else if (_wo[17]) { + _indoorList._swl_2F1L._frame = 4; + } + else if (_wo[61]) { + _indoorList._swl_2F1L._frame = 28; + } + + if (_wo[26] || _wo[29] || _wo[21]) { + } + else if (_wo[18]) { + _indoorList._swl_2F2R._frame = 7; + } + else if (_wo[62]) { + _indoorList._swl_2F2R._frame = 31; + } + + if (_wo[27] || _wo[22]) { + } + else if (_wo[19]) { + _indoorList._swl_2F1R._frame = 5; + } + else if (_wo[63]) { + _indoorList._swl_2F1R._frame = 29; + } + + if (_wo[27] && _wo[25]) { + } + else if (_wo[27] && _wo[28]) { + } + else if (_wo[23] & _wo[25]) { + } + else if (_wo[23] && _wo[28]) { + } + else if (_wo[102]) { + _indoorList._fwl_2F1L._frame = 7; + } + else if (_wo[64]) { + _indoorList._fwl_2F1L._frame = 16; + } + else if (_wo[182]) { + _indoorList._fwl_2F1L._frame = 10; + } + else if (_wo[122]) { + _indoorList._fwl_2F1L._frame = 8; + } + else if (_wo[142]) { + _indoorList._fwl_2F1L._frame = 9; + } + else if (_wo[162]) { + _indoorList._fwl_2F1L._frame = _overallFrame + 1; + } + else if (_wo[20]) { + _indoorList._fwl_2F1L._frame = 0; + } + else if (_wo[202]) { + _indoorList._fwl_2F1L._frame = 15; + } + else if (_wo[222]) { + _indoorList._fwl_2F1L._frame = 14; + } + else if (_wo[242]) { + _indoorList._fwl_2F1L._frame = 6; + } + else if (_wo[262]) { + _indoorList._fwl_2F1L._frame = 11; + } + else if (_wo[282]) { + _indoorList._fwl_2F1L._frame = 12; + } + else if (_wo[302]) { + _indoorList._fwl_2F1L._frame = 13; + } + // TODO } diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 498de3c195..43b1f31bde 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -116,6 +116,7 @@ private: int _hiliteChar; int _intrIndex1; bool _flipWtr; + bool _flipWall; bool _flag1; int _animCounter; bool _isAnimReset; @@ -125,7 +126,7 @@ private: byte _wp[20]; byte _wo[308]; bool _thinWall; - int _charsArray1[12]; + int _overallFrame; void loadSprites(); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 1a01b441f6..3650c9d98b 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1095,7 +1095,9 @@ void Map::load(int mapId) { _surfaceSprites[i].load(OUTDOOR_SURFACES[i]); } - _wallSprites._surfaces[0].clear(); + for (int i = 0; i < TOTAL_SURFACES; ++i) + _wallSprites._surfaces[i].clear(); + Common::String fwlName = Common::String::format("%s.til", TERRAIN_TYPES[_mazeData[0]._wallKind]); _wallSprites._fwl1.load(fwlName); diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 37eba7074c..d68bc2b0b8 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -360,7 +360,6 @@ private: bool _stepped; int _mazeDataIndex; bool _currentSteppedOn; - int _currentSurfaceId; void loadEvents(int mapId); @@ -385,6 +384,7 @@ public: int _currentMonsterFlags; MazeWallLayers _currentWall; int _currentTile; + int _currentSurfaceId; public: Map(XeenEngine *vm); @@ -397,6 +397,9 @@ public: void saveMaze(); int getCell(int idx); + + MazeData mazeData() { return _mazeData[0]; } + }; } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 5740a419bd..e56ad1656e 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -432,4 +432,18 @@ const byte WALL_NUMBERS[4][96] = { } }; +const int DRAW_NUMBERS[25] = { + 36, 37, 38, 43, 42, 41, 39, 20, 22, 24, 33, 31, 29, 26, 10, 11, + 18, 16, 13, 5, 9, 6, 0, 4, 1 +}; + +const int DRAW_FRAMES[25][2] = { + { 18, 24 }, { 19, 23 }, { 20, 22 }, { 10, 24 }, { 19, 23 }, { 20, 22 }, + { 21, 21 }, { 11, 17 }, { 12, 16 }, { 13, 15 }, { 11, 17 }, { 12, 16 }, + { 13, 15 }, { 14, 14 }, { 6, 10 }, { 7, 9 }, { 6, 10 }, { 7, 9 }, + { 8, 8 }, { 3, 5 }, { 3, 5 }, { 4, 4 }, { 0, 2 }, { 0, 2 }, + { 1, 1 } +}; + + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 71ac91f641..bed9569163 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -90,6 +90,10 @@ extern const int DIRECTION_ANIM_POSITIONS[4][4]; extern const byte WALL_NUMBERS[4][96]; +extern const int DRAW_NUMBERS[25]; + +extern const int DRAW_FRAMES[25][2]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From 5f2e145580ae4c10fd384933ae65b66215779fd9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 14 Jan 2015 08:48:16 -0500 Subject: XEEN: Remainder of drawIndoors implemented --- engines/xeen/combat.cpp | 1 + engines/xeen/combat.h | 1 + engines/xeen/interface.cpp | 243 ++++++++++++++++++++++++++++++++++++++++++++- engines/xeen/interface.h | 3 + engines/xeen/map.cpp | 4 +- engines/xeen/map.h | 6 +- engines/xeen/screen.cpp | 2 +- engines/xeen/xeen.cpp | 1 + engines/xeen/xeen.h | 1 + 9 files changed, 255 insertions(+), 7 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index f870083e6f..b3ef4fda71 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -32,6 +32,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm) { Common::fill(&_monsterScale[0], &_monsterScale[12], 0); Common::fill(&_elemPow[0], &_elemPow[12], 0); Common::fill(&_elemScale[0], &_elemScale[12], 0); + Common::fill(&_shooting[0], &_shooting[6], 0); } } // End of namespace Xeen diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 3360bbdddf..24a358716f 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -38,6 +38,7 @@ public: int _monsterScale[12]; int _elemPow[12]; int _elemScale[12]; + bool _shooting[6]; int _attackMon1, _attackMon2, _attackMon3; public: Combat(XeenEngine *vm); diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 12317da0ef..ec66434c5f 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -378,6 +378,8 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { _intrIndex1 = 0; _flipWtr = false; _flipWall = false; + _flipSky = false; + _flipGround = false; _flag1 = false; _animCounter = 0; _isAnimReset = false; @@ -386,6 +388,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { _objNumber = 0; _thinWall = false; _overallFrame = 0; + _isShooting = false; Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); Common::fill(&_wp[0], &_wp[20], 0); @@ -960,6 +963,7 @@ void Interface::draw3d(bool updateFlag) { const int INDOOR_COMBAT_POS[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } }; const int INDOOR_COMBAT_POS2[4] = { 8, 6, 4, 2 }; + // TODO: Double check this, since it's not being used? MazeObject &objObject = map._mobData._objects[_objNumber - 1]; for (int idx = 0; idx < 3; ++idx) { @@ -3705,7 +3709,7 @@ void Interface::drawIndoors() { } else if (_wo[122]) { _indoorList._fwl_2F1L._frame = 8; - } + } else if (_wo[142]) { _indoorList._fwl_2F1L._frame = 9; } @@ -3733,7 +3737,244 @@ void Interface::drawIndoors() { else if (_wo[302]) { _indoorList._fwl_2F1L._frame = 13; } + + if (_wo[27] && _wo[26]) { + } + else if (_wo[27] && _wo[29]) { + } + else if (_wo[24] && _wo[26]) { + } + else if (_wo[24] && _wo[29]) { + } + else if (_wo[103]) { + _indoorList._fwl_2F1R._frame = 7; + } + else if (_wo[65]) { + _indoorList._fwl_2F1R._frame = 16; + } + else if (_wo[183]) { + _indoorList._fwl_2F1R._frame = 10; + } + else if (_wo[123]) { + _indoorList._fwl_2F1R._frame = 8; + } + else if (_wo[143]) { + _indoorList._fwl_2F1R._frame = 9; + } + else if (_wo[163]) { + _indoorList._fwl_2F1R._frame = _overallFrame + 1; + } + else if (_wo[21]) { + _indoorList._fwl_2F1R._frame = 0; + } + else if (_wo[203]) { + _indoorList._fwl_2F1R._frame = 15; + } + else if (_wo[223]) { + _indoorList._fwl_2F1R._frame = 14; + } + else if (_wo[243]) { + _indoorList._fwl_2F1R._frame = 6; + } + else if (_wo[263]) { + _indoorList._fwl_2F1R._frame = 11; + } + else if (_wo[283]) { + _indoorList._fwl_2F1R._frame = 12; + } + else if (_wo[303]) { + _indoorList._fwl_2F1R._frame = 13; + } + + if (_wo[27]) { + + } + else if (_wo[104]) { + _indoorList._fwl_2F._frame = 7; + } + else if (_wo[66]) { + _indoorList._fwl_2F._frame = 16; + } + else if (_wo[184]) { + _indoorList._fwl_2F._frame = 10; + } + else if (_wo[124]) { + _indoorList._fwl_2F._frame = 8; + } + else if (_wo[144]) { + _indoorList._fwl_2F._frame = 9; + } + else if (_wo[164]) { + _indoorList._fwl_2F._frame = _overallFrame + 1; + } + else if (_wo[22]) { + _indoorList._fwl_2F._frame = 0; + } + else if (_wo[204]) { + _indoorList._fwl_2F._frame = 15; + } + else if (_wo[224]) { + _indoorList._fwl_2F._frame = 14; + } + else if (_wo[244]) { + _indoorList._fwl_2F._frame = 6; + } + else if (_wo[264]) { + _indoorList._fwl_2F._frame = 11; + } + else if (_wo[284]) { + _indoorList._fwl_2F._frame = 12; + } + else if (_wo[304]) { + _indoorList._fwl_2F._frame = 13; + } + + if (_wo[27]) { + } + else if (_wo[23]) { + _indoorList._swl_1F1L._frame = 2; + } + else if (_wo[67]) { + _indoorList._swl_1F1L._frame = 26; + } + + if (_wo[27]) { + } + else if (_wo[24]) { + _indoorList._swl_1F1R._frame = 3; + } + else if (_wo[68]) { + _indoorList._swl_1F1R._frame = 27; + } + + if (_wo[28]) { + } + else if (_wo[105] || _wo[25] || _wo[165] || _wo[125] || _wo[185] || _wo[145]) { + _indoorList._fwl_1F1L._frame = 0; + _indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl1; + } + else if (_wo[69]) { + _indoorList._fwl_1F1L._frame = 9; + _indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl2; + } + + if (_wo[29]) { + } + else if (_wo[106] || _wo[26] || _wo[166] || _wo[126] || _wo[186] || _wo[146]) { + _indoorList._fwl_1F._frame = 0; + _indoorList._fwl_1F._sprites = &map._wallSprites._fwl1; + } + else if (_wo[70]) { + _indoorList._fwl_1F._frame = 9; + _indoorList._fwl_1F._sprites = &map._wallSprites._fwl2; + } + + if (_wo[107]) { + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + if (_vm->_openDoor) + _indoorList._fwl_1F1R._frame = 0; + else + _indoorList._fwl_1F1R._frame = map.mazeData()._wallKind ? 1 : 10; + } + else if (_wo[71]) { + _indoorList._fwl_1F1R._frame = 9; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[167]) { + _indoorList._fwl_1F1R._frame = _overallFrame + 1; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[127]) { + _indoorList._fwl_1F1R._frame = 1; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[147]) { + _indoorList._fwl_1F1R._frame = 2; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[187]) { + _indoorList._fwl_1F1R._frame = 3; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[27]) { + _indoorList._fwl_1F1R._frame = 0; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1; + } + else if (_wo[207]) { + _indoorList._fwl_1F1R._frame = 8; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[227]) { + _indoorList._fwl_1F1R._frame = 7; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[247]) { + _indoorList._fwl_1F1R._frame = 6; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1; + } + else if (_wo[267]) { + _indoorList._fwl_1F1R._frame = 4; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[287]) { + _indoorList._fwl_1F1R._frame = 5; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[307]) { + _indoorList._fwl_1F1R._frame = 6; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + + if (_wo[28]) { + _indoorList._swl_0F1L._frame = 0; + } + else if (_wo[72]) { + _indoorList._swl_0F1L._frame = 24; + } + + if (_wo[29]) { + _indoorList._swl_0F1R._frame = 1; + } + else if (_wo[73]) { + _indoorList._swl_0F1R._frame = 25; + } + + map.cellFlagLookup(_vm->_party._mazePosition); + + // WORKAROUND: Original did an array lookup on _skySprites. + // Was this a feature for multiple skys that was abandoned? + _indoorList[0]._sprites = &map._skySprites; + _indoorList[0]._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0; + + if (_vm->_openDoor) { + Common::Point pt( + _vm->_party._mazePosition.x + SCREEN_POSITIONING_X[ + _vm->_party._mazeDirection][_vm->_party._mazePosition.x], + _vm->_party._mazePosition.y + SCREEN_POSITIONING_Y[ + _vm->_party._mazeDirection][_vm->_party._mazePosition.y] + ); + map.cellFlagLookup(pt); + + _indoorList._sky._sprites = &map._skySprites; + } else { + _indoorList._sky._sprites = _indoorList[0]._sprites; + } + + _indoorList._sky._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0; + _indoorList._ground._flags = _flipGround ? SPRFLAG_HORIZ_FLIPPED : 0; + _indoorList._horizon._frame = 7; + + // Finally draw the darn indoor scene + _vm->_screen->_windows[3].drawList(&_indoorList[0], _indoorList.size()); + + // Check for any character shooting + _isShooting = false; + for (int i = 0; i < _vm->_party._partyCount; ++i) { + if (_vm->_combat->_shooting[i]) + _isShooting = true; + } + _charsShooting = _isShooting; // TODO } diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 43b1f31bde..f84885f307 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -117,6 +117,8 @@ private: int _intrIndex1; bool _flipWtr; bool _flipWall; + bool _flipSky; + bool _flipGround; bool _flag1; int _animCounter; bool _isAnimReset; @@ -127,6 +129,7 @@ private: byte _wo[308]; bool _thinWall; int _overallFrame; + bool _isShooting; void loadSprites(); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 3650c9d98b..e410333d0d 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -861,7 +861,7 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { _currentCantRest = false; _currentIsDrain = false; _currentIsEvent = false; - _currentIsObject = false; + _currentSky = false; _currentMonsterFlags = 0; } @@ -1330,7 +1330,7 @@ void Map::cellFlagLookup(const Common::Point &pt) { _currentCantRest = cell._flags & FLAG_WATER; _currentIsDrain = cell._flags & OUTFLAG_DRAIN; _currentIsEvent = cell._flags & FLAG_AUTOEXECUTE_EVENT; - _currentIsObject = cell._flags & OUTFLAG_OBJECT_EXISTS; + _currentSky = cell._flags & OUTFLAG_OBJECT_EXISTS; _currentMonsterFlags = cell._flags & 7; } diff --git a/engines/xeen/map.h b/engines/xeen/map.h index d68bc2b0b8..faffe97c97 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -362,8 +362,6 @@ private: bool _currentSteppedOn; void loadEvents(int mapId); - - void cellFlagLookup(const Common::Point &pt); public: bool _isOutdoors; MonsterObjectData _mobData; @@ -380,7 +378,7 @@ public: bool _currentCantRest; bool _currentIsDrain; bool _currentIsEvent; - bool _currentIsObject; + bool _currentSky; int _currentMonsterFlags; MazeWallLayers _currentWall; int _currentTile; @@ -392,6 +390,8 @@ public: int mazeLookup(const Common::Point &pt, int directionLayerIndex); + void cellFlagLookup(const Common::Point &pt); + void setCellSurfaceFlags(const Common::Point &pt, int bits); void saveMaze(); diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index cfde7804ae..783f1ffbf4 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -170,7 +170,7 @@ void Window::drawList(DrawStruct *items, int count) { Screen &screen = *_vm->_screen; for (int i = 0; i < count; ++i, ++items) { - if (items->_frame == -1 || items->_scale == -1) + if (items->_frame == -1 || items->_scale == -1 || items->_sprites == nullptr) continue; Common::Rect bounds = _innerBounds; diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index c749129678..b3758b57ed 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -54,6 +54,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _falling = 0; _moveMonsters = false; _mode = MODE_0; + _openDoor = 0; } XeenEngine::~XeenEngine() { diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 59279771d5..e6bcd8c0b7 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -146,6 +146,7 @@ public: bool _noDirectionSense; int _falling; bool _moveMonsters; + int _openDoor; public: XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); virtual ~XeenEngine(); -- cgit v1.2.3 From e6383519a167eebdbf5877e81c2e9e32e6a101a3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 14 Jan 2015 20:39:56 -0500 Subject: XEEN: Split in-game scene draw code into a separate file --- engines/xeen/interface.cpp | 1679 +-------------------------------------- engines/xeen/interface.h | 76 +- engines/xeen/interface_map.cpp | 1704 ++++++++++++++++++++++++++++++++++++++++ engines/xeen/interface_map.h | 118 +++ engines/xeen/module.mk | 1 + 5 files changed, 1831 insertions(+), 1747 deletions(-) create mode 100644 engines/xeen/interface_map.cpp create mode 100644 engines/xeen/interface_map.h (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index ec66434c5f..deb8761b06 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -27,340 +27,7 @@ namespace Xeen { -OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]) { - _data[0] = DrawStruct(0, 8, 8); - _data[1] = DrawStruct(1, 8, 25); - _data[2] = DrawStruct(0, 8, 67); - _data[3] = DrawStruct(0, 8, 67); - _data[4] = DrawStruct(0, 38, 67); - _data[5] = DrawStruct(0, 84, 67); - _data[6] = DrawStruct(0, 134, 67); - _data[7] = DrawStruct(0, 117, 67); - _data[8] = DrawStruct(0, 117, 67); - _data[9] = DrawStruct(0, 103, 67); - _data[10] = DrawStruct(0, 8, 73); - _data[11] = DrawStruct(0, 8, 73); - _data[12] = DrawStruct(0, 30, 73); - _data[13] = DrawStruct(0, 181, 73); - _data[14] = DrawStruct(0, 154, 73); - _data[15] = DrawStruct(0, 129, 73); - _data[16] = DrawStruct(0, 87, 73); - _data[17] = DrawStruct(0, 8, 81); - _data[18] = DrawStruct(0, 8, 81); - _data[19] = DrawStruct(0, 202, 81); - _data[20] = DrawStruct(0, 145, 81); - _data[21] = DrawStruct(0, 63, 81); - _data[22] = DrawStruct(0, 8, 93); - _data[23] = DrawStruct(0, 169, 93); - _data[24] = DrawStruct(0, 31, 93); - _data[25] = DrawStruct(0, 8, 109); - _data[26] = DrawStruct(0, 201, 109); - _data[27] = DrawStruct(0, 8, 109); - _data[28] = DrawStruct(1, 65472, 61, 14, SPRFLAG_2000); - _data[29] = DrawStruct(1, 65496, 61, 14, 0); - _data[30] = DrawStruct(1, 65520, 61, 14, 0); - _data[31] = DrawStruct(1, 8, 61, 14, 0); - _data[32] = DrawStruct(1, 128, 61, 14, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000); - _data[33] = DrawStruct(1, 104, 61, 14, SPRFLAG_HORIZ_FLIPPED); - _data[34] = DrawStruct(1, 80, 61, 14, SPRFLAG_HORIZ_FLIPPED); - _data[35] = DrawStruct(1, 56, 61, 14, SPRFLAG_HORIZ_FLIPPED); - _data[36] = DrawStruct(1, 32, 61, 14, 0); - _data[37] = DrawStruct(0, 65527, 61, 14, 0); - _data[38] = DrawStruct(0, 65478, 61, 14, 0); - _data[39] = DrawStruct(0, 40, 61, 14, 0); - _data[40] = DrawStruct(0, 65454, 61, 14, 0); - _data[41] = DrawStruct(0, 64, 61, 14, 0); - _data[42] = DrawStruct(0, 65495, 61, 14, 0); - _data[43] = DrawStruct(0, 65510, 61, 14, 0); - _data[44] = DrawStruct(0, 65502, 61, 14, 0); - _data[45] = DrawStruct(0, 65520, 61, 14, 0); - _data[46] = DrawStruct(0, 23, 61, 14, 0); - _data[47] = DrawStruct(0, 16, 61, 14, 0); - _data[48] = DrawStruct(0, 65478, 61, 14, 0); - _data[49] = DrawStruct(0, 40, 61, 14, 0); - _data[50] = DrawStruct(0, 65519, 61, 14, 0); - _data[51] = DrawStruct(0, 65535, 58, 14, 0); - _data[52] = DrawStruct(0, 65527, 58, 14, 0); - _data[53] = DrawStruct(0, 72, 58, 12, 0); - _data[54] = DrawStruct(0, 72, 58, 12, SPRFLAG_HORIZ_FLIPPED); - _data[55] = DrawStruct(0, 69, 63, 12, 0); - _data[56] = DrawStruct(0, 75, 63, 12, SPRFLAG_HORIZ_FLIPPED); - _data[57] = DrawStruct(0, 73, 53, 12, 0); - _data[58] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED); - _data[59] = DrawStruct(0, 80, 57, 12, 0); - _data[60] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED); - _data[61] = DrawStruct(2, 65525, 54, 8, 0); - _data[62] = DrawStruct(1, 65515, 54, 11, 0); - _data[63] = DrawStruct(2, 165, 54, 8, SPRFLAG_HORIZ_FLIPPED); - _data[64] = DrawStruct(1, 86, 54, 11, SPRFLAG_HORIZ_FLIPPED); - _data[65] = DrawStruct(1, 33, 54, 11, 0); - _data[66] = DrawStruct(0, 65528, 54, 12, 0); - _data[67] = DrawStruct(0, 65463, 54, 12, 0); - _data[68] = DrawStruct(0, 57, 54, 12, 0); - _data[69] = DrawStruct(0, 65471, 54, 12, 0); - _data[70] = DrawStruct(0, 65455, 54, 12, 0); - _data[71] = DrawStruct(0, 49, 54, 12, 0); - _data[72] = DrawStruct(0, 65, 54, 12, 0); - _data[73] = DrawStruct(0, 65512, 54, 12, 0); - _data[74] = DrawStruct(0, 9, 50, 12, 0); - _data[75] = DrawStruct(0, 65528, 50, 12, 0); - _data[76] = DrawStruct(0, 72, 53, 8, 0); - _data[77] = DrawStruct(0, 72, 53, 8, SPRFLAG_HORIZ_FLIPPED); - _data[78] = DrawStruct(0, 77, 58, 8, 0); - _data[79] = DrawStruct(0, 67, 58, 8, SPRFLAG_HORIZ_FLIPPED); - _data[80] = DrawStruct(0, 81, 47, 8, 0); - _data[81] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED); - _data[82] = DrawStruct(0, 94, 52, 8, 0); - _data[83] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED); - _data[84] = DrawStruct(2, 8, 40); - _data[85] = DrawStruct(2, 146, 40, 0, SPRFLAG_HORIZ_FLIPPED); - _data[86] = DrawStruct(1, 32, 40, 6, 0); - _data[87] = DrawStruct(0, 65529, 30, 7, 0); - _data[88] = DrawStruct(0, 65424, 30, 7, SPRFLAG_2000); - _data[89] = DrawStruct(0, 98, 30, 7, SPRFLAG_2000); - _data[90] = DrawStruct(0, 65424, 30, 8, SPRFLAG_2000); - _data[91] = DrawStruct(0, 98, 30, 8, SPRFLAG_2000); - _data[92] = DrawStruct(0, 65498, 30, 8, 0); - _data[93] = DrawStruct(0, 25, 30, 8, 0); - _data[94] = DrawStruct(0, 65529, 30, 8, 0); - _data[95] = DrawStruct(0, 72, 48, 4, 0); - _data[96] = DrawStruct(0, 72, 48, 4, SPRFLAG_HORIZ_FLIPPED); - _data[97] = DrawStruct(0, 85, 53, 4, 0); - _data[98] = DrawStruct(0, 59, 53, 4, SPRFLAG_HORIZ_FLIPPED); - _data[99] = DrawStruct(0, 89, 41, 4, 0); - _data[100] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED); - _data[101] = DrawStruct(0, 106, 47, 4, 0); - _data[102] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED); - _data[103] = DrawStruct(0, 8, 24); - _data[104] = DrawStruct(0, 169, 24, 0, SPRFLAG_HORIZ_FLIPPED); - _data[105] = DrawStruct(1, 32, 24); - _data[106] = DrawStruct(0, 65513, 40, 0, SPRFLAG_2000); - _data[107] = DrawStruct(0, 200, 40, 0, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000); - _data[108] = DrawStruct(0, 8, 47); - _data[109] = DrawStruct(0, 169, 47, 0, SPRFLAG_HORIZ_FLIPPED); - _data[110] = DrawStruct(1, 65480, 65532, 32768, SPRFLAG_4000 | SPRFLAG_2000); - _data[111] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); - _data[112] = DrawStruct(0, 65469, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); - _data[113] = DrawStruct(0, 44, 73); - _data[114] = DrawStruct(0, 44, 73); - _data[115] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); - _data[116] = DrawStruct(0, 169, 73); - _data[117] = DrawStruct(0, 169, 73); - _data[118] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); - _data[119] = DrawStruct(0, 110, 73); - _data[120] = DrawStruct(0, 110, 73); - _data[121] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); - _data[122] = DrawStruct(0, 110, 73); - _data[123] = DrawStruct(0, 110, 73); - _data[124] = DrawStruct(0, 72, 43); - _data[125] = DrawStruct(0, 72, 43, 0, SPRFLAG_HORIZ_FLIPPED); - _data[126] = DrawStruct(0, 93, 48); - _data[127] = DrawStruct(0, 51, 48, 0, SPRFLAG_HORIZ_FLIPPED); - _data[128] = DrawStruct(0, 97, 36); - _data[129] = DrawStruct(0, 47, 36, 0, SPRFLAG_HORIZ_FLIPPED); - _data[130] = DrawStruct(0, 118, 42); - _data[131] = DrawStruct(0, 26, 42, 0, SPRFLAG_HORIZ_FLIPPED); -} - -/*------------------------------------------------------------------------*/ - -IndoorDrawList::IndoorDrawList() : - _sky(_data[1]), _ground(_data[2]), _horizon(_data[28]), - _swl_0F1R(_data[ 46]), _swl_0F1L(_data[44]), _swl_1F1R(_data[134]), - _swl_1F1L(_data[133]), _swl_2F2R(_data[110]), _swl_2F1R(_data[109]), - _swl_2F1L(_data[108]), _swl_2F2L(_data[107]), _swl_3F1R(_data[ 78]), - _swl_3F2R(_data[ 77]), _swl_3F3R(_data[ 76]), _swl_3F4R(_data[ 75]), - _swl_3F1L(_data[ 74]), _swl_3F2L(_data[ 73]), _swl_3F3L(_data[ 72]), - _swl_3F4L(_data[ 71]), _swl_4F4R(_data[ 33]), _swl_4F3R(_data[ 34]), - _swl_4F2R(_data[ 35]), _swl_4F1R(_data[ 36]), _swl_4F1L(_data[ 32]), - _swl_4F2L(_data[ 31]), _swl_4F3L(_data[ 30]), _swl_4F4L(_data[ 29]), - _fwl_4F4R(_data[ 45]), _fwl_4F3R(_data[ 44]), _fwl_4F2R(_data[ 43]), - _fwl_4F1R(_data[ 42]), _fwl_4F( _data[ 41]), _fwl_4F1L(_data[ 40]), - _fwl_4F2L(_data[ 39]), _fwl_4F3L(_data[ 38]), _fwl_4F4L(_data[ 37]), - _fwl_2F1R(_data[121]), _fwl_2F( _data[120]), _fwl_2F1L(_data[119]), - _fwl_3F2R(_data[ 91]), _fwl_3F1R(_data[ 90]), _fwl_3F( _data[ 89]), - _fwl_3F1L(_data[ 88]), _fwl_3F2L(_data[ 87]), _fwl_1F( _data[147]), - _fwl_1F1R(_data[145]), _fwl_1F1L(_data[143]), - _objects0(_data[149]), _objects1(_data[125]), _objects2(_data[126]), - _objects3(_data[127]), _objects4(_data[97]), _objects5(_data[98]), - _objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]), - _objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]) { - // Setup draw structure positions - _data[0] = DrawStruct(0, 8, 8); - _data[1] = DrawStruct(1, 8, 25); - _data[2] = DrawStruct(0, 8, 67); - _data[3] = DrawStruct(0, 8, 67); - _data[4] = DrawStruct(0, 38, 67); - _data[5] = DrawStruct(0, 84, 67); - _data[6] = DrawStruct(0, 134, 67); - _data[7] = DrawStruct(0, 117, 67); - _data[8] = DrawStruct(0, 117, 67); - _data[9] = DrawStruct(0, 103, 67); - _data[10] = DrawStruct(0, 8, 73); - _data[11] = DrawStruct(0, 8, 73); - _data[12] = DrawStruct(0, 30, 73); - _data[13] = DrawStruct(0, 181, 73); - _data[14] = DrawStruct(0, 154, 73); - _data[15] = DrawStruct(0, 129, 73); - _data[16] = DrawStruct(0, 87, 73); - _data[17] = DrawStruct(0, 8, 81); - _data[18] = DrawStruct(0, 8, 81); - _data[19] = DrawStruct(0, 202, 81); - _data[20] = DrawStruct(0, 145, 81); - _data[21] = DrawStruct(0, 63, 81); - _data[22] = DrawStruct(0, 8, 93); - _data[23] = DrawStruct(0, 169, 93); - _data[24] = DrawStruct(0, 31, 93); - _data[25] = DrawStruct(0, 8, 109); - _data[26] = DrawStruct(0, 201, 109); - _data[27] = DrawStruct(0, 8, 109); - _data[28] = DrawStruct(7, 8, 64); - _data[29] = DrawStruct(22, 32, 60); - _data[30] = DrawStruct(20, 56, 60); - _data[31] = DrawStruct(18, 80, 60); - _data[32] = DrawStruct(16, 104, 60); - _data[33] = DrawStruct(23, 152, 60, 0, SPRFLAG_HORIZ_FLIPPED); - _data[34] = DrawStruct(21, 144, 60, 0, SPRFLAG_HORIZ_FLIPPED); - _data[35] = DrawStruct(19, 131, 60, 0, SPRFLAG_HORIZ_FLIPPED); - _data[36] = DrawStruct(17, 120, 60, 0, SPRFLAG_HORIZ_FLIPPED); - _data[37] = DrawStruct(14, 8, 60); - _data[38] = DrawStruct(12, 32, 60); - _data[39] = DrawStruct(10, 56, 60); - _data[40] = DrawStruct(14, 80, 60); - _data[41] = DrawStruct(14, 104, 60); - _data[42] = DrawStruct(14, 128, 60); - _data[43] = DrawStruct(14, 152, 60); - _data[44] = DrawStruct(8, 176, 60); - _data[45] = DrawStruct(8, 200, 60); - _data[46] = DrawStruct(0, 65472, 61, 14, 0); - _data[47] = DrawStruct(0, 65496, 61, 14, 0); - _data[48] = DrawStruct(0, 65520, 61, 14, 0); - _data[49] = DrawStruct(0, 8, 61, 14, 0); - _data[50] = DrawStruct(0, 32, 61, 14, 0); - _data[51] = DrawStruct(0, 56, 61, 14, 0); - _data[52] = DrawStruct(0, 80, 61, 14, 0); - _data[53] = DrawStruct(0, 104, 61, 14, 0); - _data[54] = DrawStruct(0, 128, 61, 14, 0); - _data[55] = DrawStruct(0, 65527, 58, 14, 0); - _data[56] = DrawStruct(0, 65502, 58, 14, 0); - _data[57] = DrawStruct(0, 16, 58, 14, 0); - _data[58] = DrawStruct(0, 65478, 58, 14, 0); - _data[59] = DrawStruct(0, 40, 58, 14, 0); - _data[60] = DrawStruct(0, 65495, 58, 14, 0); - _data[61] = DrawStruct(0, 65510, 58, 14, 0); - _data[62] = DrawStruct(0, 65502, 58, 14, 0); - _data[63] = DrawStruct(0, 65520, 58, 14, 0); - _data[64] = DrawStruct(0, 23, 58, 14, 0); - _data[65] = DrawStruct(0, 16, 58, 14, 0); - _data[66] = DrawStruct(0, 65478, 58, 14, 0); - _data[67] = DrawStruct(0, 40, 58, 14, 0); - _data[68] = DrawStruct(0, 65519, 58, 14, 0); - _data[69] = DrawStruct(0, 65535, 58, 14, 0); - _data[70] = DrawStruct(0, 65527, 58, 14, 0); - _data[71] = DrawStruct(14, 8, 58); - _data[72] = DrawStruct(12, 8, 55); - _data[73] = DrawStruct(10, 32, 52); - _data[74] = DrawStruct(14, 88, 52); - _data[75] = DrawStruct(14, 128, 52, 0, SPRFLAG_HORIZ_FLIPPED); - _data[76] = DrawStruct(14, 152, 52, 0, SPRFLAG_HORIZ_FLIPPED); - _data[77] = DrawStruct(0, 176, 55, 0, SPRFLAG_HORIZ_FLIPPED); - _data[78] = DrawStruct(0, 200, 58, 0, SPRFLAG_HORIZ_FLIPPED); - _data[79] = DrawStruct(0, 72, 58, 12, 0); - _data[80] = DrawStruct(0, 72, 58, 12, SPRFLAG_HORIZ_FLIPPED); - _data[81] = DrawStruct(0, 69, 63, 12, 0); - _data[82] = DrawStruct(0, 75, 63, 12, SPRFLAG_HORIZ_FLIPPED); - _data[83] = DrawStruct(0, 73, 53, 12, 0); - _data[84] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED); - _data[85] = DrawStruct(0, 80, 57, 12, 0); - _data[86] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED); - _data[87] = DrawStruct(7, 65512, 52, 0, SPRFLAG_2000); - _data[88] = DrawStruct(7, 32, 52); - _data[89] = DrawStruct(7, 88, 52); - _data[90] = DrawStruct(0, 144, 52); - _data[91] = DrawStruct(0, 200, 52, 0, SPRFLAG_2000); - _data[92] = DrawStruct(0, 65457, 52, 11, SPRFLAG_2000); - _data[93] = DrawStruct(0, 65509, 52, 11, 0); - _data[94] = DrawStruct(0, 32, 52, 11, 0); - _data[95] = DrawStruct(0, 89, 52, 11, 0); - _data[96] = DrawStruct(0, 145, 52, 11, SPRFLAG_2000); - _data[97] = DrawStruct(0, 65528, 50, 12, 0); - _data[98] = DrawStruct(0, 65471, 50, 12, 0); - _data[99] = DrawStruct(0, 49, 50, 12, 0); - _data[100] = DrawStruct(0, 65471, 50, 12, 0); - _data[101] = DrawStruct(0, 65455, 50, 12, 0); - _data[102] = DrawStruct(0, 49, 50, 12, 0); - _data[103] = DrawStruct(0, 65, 50, 12, 0); - _data[104] = DrawStruct(0, 65512, 50, 12, 0); - _data[105] = DrawStruct(0, 9, 50, 12, 0); - _data[106] = DrawStruct(0, 65528, 50, 12, 0); - _data[107] = DrawStruct(7, 8, 48); - _data[108] = DrawStruct(7, 64, 40); - _data[109] = DrawStruct(6, 144, 40, 0, SPRFLAG_HORIZ_FLIPPED); - _data[110] = DrawStruct(6, 200, 48, 0, SPRFLAG_HORIZ_FLIPPED); - _data[111] = DrawStruct(0, 72, 53, 8, 0); - _data[112] = DrawStruct(0, 72, 53, 8, SPRFLAG_HORIZ_FLIPPED); - _data[113] = DrawStruct(0, 77, 58, 8, 0); - _data[114] = DrawStruct(0, 67, 58, 8, SPRFLAG_HORIZ_FLIPPED); - _data[115] = DrawStruct(0, 81, 47, 8, 0); - _data[116] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED); - _data[117] = DrawStruct(0, 94, 52, 8, 0); - _data[118] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED); - _data[119] = DrawStruct(6, 65496, 40, 0, SPRFLAG_2000); - _data[120] = DrawStruct(6, 64, 40); - _data[121] = DrawStruct(0, 168, 40, 0, SPRFLAG_2000); - _data[122] = DrawStruct(0, 65464, 40, 6, SPRFLAG_2000); - _data[123] = DrawStruct(0, 32, 40, 6, 0); - _data[124] = DrawStruct(0, 137, 40, 6, SPRFLAG_2000); - _data[125] = DrawStruct(0, 65529, 25, 7, 0); - _data[126] = DrawStruct(0, 65424, 25, 7, SPRFLAG_2000); - _data[127] = DrawStruct(0, 98, 25, 7, SPRFLAG_2000); - _data[128] = DrawStruct(0, 65424, 29, 8, SPRFLAG_2000); - _data[129] = DrawStruct(0, 98, 29, 8, SPRFLAG_2000); - _data[130] = DrawStruct(0, 65498, 29, 8, 0); - _data[131] = DrawStruct(0, 25, 29, 8, 0); - _data[132] = DrawStruct(0, 65529, 29, 8, 0); - _data[133] = DrawStruct(6, 32, 24); - _data[134] = DrawStruct(0, 168, 24, 0, SPRFLAG_HORIZ_FLIPPED); - _data[135] = DrawStruct(0, 72, 48, 4, 0); - _data[136] = DrawStruct(0, 72, 48, 4, SPRFLAG_HORIZ_FLIPPED); - _data[137] = DrawStruct(0, 85, 53, 4, 0); - _data[138] = DrawStruct(0, 59, 53, 4, SPRFLAG_HORIZ_FLIPPED); - _data[139] = DrawStruct(0, 89, 41, 4, 0); - _data[140] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED); - _data[141] = DrawStruct(0, 106, 47, 4, 0); - _data[142] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED); - _data[143] = DrawStruct(0, 65400, 24, 0, SPRFLAG_2000); - _data[144] = DrawStruct(0, 8, 12); - _data[145] = DrawStruct(0, 32, 24); - _data[146] = DrawStruct(0, 200, 12, 0, SPRFLAG_HORIZ_FLIPPED); - _data[147] = DrawStruct(0, 200, 24, 0, SPRFLAG_2000); - _data[148] = DrawStruct(0, 32, 24); - _data[149] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); - _data[150] = DrawStruct(0, 65469, 10, 0, SPRFLAG_4000 | SPRFLAG_2000); - _data[151] = DrawStruct(0, 44, 73); - _data[152] = DrawStruct(0, 44, 73); - _data[153] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); - _data[154] = DrawStruct(0, 169, 73); - _data[155] = DrawStruct(0, 169, 73); - _data[156] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); - _data[157] = DrawStruct(0, 110, 73); - _data[158] = DrawStruct(0, 110, 73); - _data[159] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); - _data[160] = DrawStruct(0, 110, 73); - _data[161] = DrawStruct(0, 110, 73); - _data[162] = DrawStruct(0, 72, 43); - _data[163] = DrawStruct(0, 72, 43, 0, SPRFLAG_HORIZ_FLIPPED); - _data[164] = DrawStruct(0, 93, 48); - _data[165] = DrawStruct(0, 51, 48, 0, SPRFLAG_HORIZ_FLIPPED); - _data[166] = DrawStruct(0, 97, 36); - _data[167] = DrawStruct(0, 47, 36, 0, SPRFLAG_HORIZ_FLIPPED); - _data[168] = DrawStruct(0, 118, 42); - _data[169] = DrawStruct(0, 26, 42, 0, SPRFLAG_HORIZ_FLIPPED); -} - -/*------------------------------------------------------------------------*/ - -Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { +Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(vm) { Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr); _batUIFrame = 0; _spotDoorsUIFrame = 0; @@ -376,27 +43,18 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) { _buttonsLoaded = false; _hiliteChar = -1; _intrIndex1 = 0; - _flipWtr = false; - _flipWall = false; - _flipSky = false; - _flipGround = false; _flag1 = false; _animCounter = 0; _isAnimReset = false; - _charsShooting = false; _tillMove = 0; - _objNumber = 0; _thinWall = false; _overallFrame = 0; - _isShooting = false; Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); - Common::fill(&_wp[0], &_wp[20], 0); - Common::fill(&_wo[0], &_wo[308], 0); - initDrawStructs(); } + void Interface::initDrawStructs() { _faceDrawStructs[0] = DrawStruct(0, 0, 0); _faceDrawStructs[1] = DrawStruct(0, 101, 0); @@ -963,8 +621,8 @@ void Interface::draw3d(bool updateFlag) { const int INDOOR_COMBAT_POS[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } }; const int INDOOR_COMBAT_POS2[4] = { 8, 6, 4, 2 }; - // TODO: Double check this, since it's not being used? - MazeObject &objObject = map._mobData._objects[_objNumber - 1]; + // Double check this, since it's not being used? + //MazeObject &objObject = map._mobData._objects[_objNumber - 1]; for (int idx = 0; idx < 3; ++idx) { DrawStruct &ds1 = _indoorList[INDOOR_INDEXES[idx]]; @@ -1091,201 +749,6 @@ void Interface::animate3d() { } -void Interface::setIndoorsMonsters() { - -} - -void Interface::setIndoorObjects() { - Common::Point mazePos = _vm->_party._mazePosition; - _objNumber = 0; - const int8 *posOffset = &SCREEN_POSITIONING_X[_vm->_party._mazeDirection][0]; - Common::Point pt; - - Common::Array<MazeObject> &objects = _vm->_map->_mobData._objects; - for (uint idx = 0; idx < objects.size(); ++idx) { - MazeObject &mazeObject = objects[idx]; - - // Determine which half of the X/Y lists to use - int listOffset; - if (_vm->_files->_isDarkCc) { - listOffset = mazeObject._spriteId == 47 ? 1 : 0; - } - else { - listOffset = mazeObject._spriteId == 113 ? 1 : 0; - } - - // Position 1 - pt = Common::Point(mazePos.x + posOffset[2], mazePos.y + posOffset[194]); - if (pt == mazeObject._position && _indoorList._objects0._frame == -1) { - _indoorList._objects0._x = INDOOR_OBJECT_X[listOffset][0]; - _indoorList._objects0._y = INDOOR_OBJECT_Y[listOffset][0]; - _indoorList._objects0._frame = mazeObject._frame; - _indoorList._objects0._sprites = mazeObject._sprites; - _indoorList._objects0._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects0._flags |= SPRFLAG_HORIZ_FLIPPED; - _objNumber = idx; - } - - // Position 2 - pt = Common::Point(mazePos.x + posOffset[7], mazePos.y + posOffset[199]); - if (pt == mazeObject._position && !_wo[27] && _indoorList._objects1._frame == -1) { - _indoorList._objects1._x = INDOOR_OBJECT_X[listOffset][1]; - _indoorList._objects1._y = INDOOR_OBJECT_Y[listOffset][1]; - _indoorList._objects1._frame = mazeObject._frame; - _indoorList._objects1._sprites = mazeObject._sprites; - _indoorList._objects1._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects1._flags |= SPRFLAG_HORIZ_FLIPPED; - } - - // Position 3 - pt = Common::Point(mazePos.x + posOffset[5], mazePos.y + posOffset[197]); - if (pt == mazeObject._position && (!_wo[27] || !_wo[25]) && (!_wo[27] || !_wo[28]) && - (!_wo[23] || !_wo[25]) && (!_wo[23] || !_wo[28]) && - _indoorList._objects2._frame == -1) { - _indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][2]; - _indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][2]; - _indoorList._objects2._frame = mazeObject._frame; - _indoorList._objects2._sprites = mazeObject._sprites; - _indoorList._objects2._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects2._flags |= SPRFLAG_HORIZ_FLIPPED; - } - - // Position 4 - pt = Common::Point(mazePos.x + posOffset[9], mazePos.y + posOffset[201]); - if (pt == mazeObject._position && (!_wo[27] || !_wo[26]) && (!_wo[27] || !_wo[29]) && - (!_wo[24] || !_wo[26]) && (!_wo[24] || !_wo[29]) && _indoorList._objects3._frame == -1) { - _indoorList._objects3._x = INDOOR_OBJECT_X[listOffset][3]; - _indoorList._objects3._y = INDOOR_OBJECT_Y[listOffset][3]; - _indoorList._objects3._frame = mazeObject._frame; - _indoorList._objects3._sprites = mazeObject._sprites; - _indoorList._objects3._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects3._flags |= SPRFLAG_HORIZ_FLIPPED; - } - - // Position 5 - pt = Common::Point(mazePos.x + posOffset[14], mazePos.y + posOffset[206]); - if (pt == mazeObject._position && !_wo[22] && !_wo[27] && _indoorList._objects4._frame == -1) { - _indoorList._objects4._x = INDOOR_OBJECT_X[listOffset][4]; - _indoorList._objects4._y = INDOOR_OBJECT_Y[listOffset][4]; - _indoorList._objects4._frame = mazeObject._frame; - _indoorList._objects4._sprites = mazeObject._sprites; - _indoorList._objects4._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects4._flags |= SPRFLAG_HORIZ_FLIPPED; - } - - // Position 6 - pt = Common::Point(mazePos.x + posOffset[12], mazePos.y + posOffset[204]); - if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[23]) && (!_wo[22] || !_wo[20]) && - (!_wo[23] || !_wo[17]) && (!_wo[20] || !_wo[17]) && _indoorList._objects5._frame == -1) { - _indoorList._objects5._x = INDOOR_OBJECT_X[listOffset][5]; - _indoorList._objects5._y = INDOOR_OBJECT_Y[listOffset][5]; - _indoorList._objects5._frame = mazeObject._frame; - _indoorList._objects5._sprites = mazeObject._sprites; - _indoorList._objects5._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects5._flags |= SPRFLAG_HORIZ_FLIPPED; - } - - // Position 7 - pt = Common::Point(mazePos.x + posOffset[16], mazePos.y + posOffset[208]); - if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[24]) && (!_wo[22] || !_wo[21]) && - (!_wo[24] || !_wo[19]) && (!_wo[21] || !_wo[19]) && _indoorList._objects6._frame == -1) { - _indoorList._objects6._x = INDOOR_OBJECT_X[listOffset][6]; - _indoorList._objects6._y = INDOOR_OBJECT_Y[listOffset][6]; - _indoorList._objects6._frame = mazeObject._frame; - _indoorList._objects6._sprites = mazeObject._sprites; - _indoorList._objects6._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects6._flags |= SPRFLAG_HORIZ_FLIPPED; - } - - // Position 8 - pt = Common::Point(mazePos.x + posOffset[27], mazePos.y + posOffset[219]); - if (pt == mazeObject._position && !_wo[27] && !_wo[22] && !_wo[15] && _indoorList._objects7._frame == -1) { - _indoorList._objects7._x = INDOOR_OBJECT_X[listOffset][7]; - _indoorList._objects7._y = INDOOR_OBJECT_Y[listOffset][7]; - _indoorList._objects7._frame = mazeObject._frame; - _indoorList._objects7._sprites = mazeObject._sprites; - _indoorList._objects7._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects7._flags |= SPRFLAG_HORIZ_FLIPPED; - } - - // Position 9 - pt = Common::Point(mazePos.x + posOffset[25], mazePos.y + posOffset[217]); - if (pt == mazeObject._position && !_wo[27] && (!_wo[15] || !_wo[17]) && (!_wo[15] || !_wo[12]) && - (!_wo[12] || !_wo[7]) && (!_wo[17] || !_wo[7]) && _indoorList._objects5._frame == -1) { - _indoorList._objects8._x = INDOOR_OBJECT_X[listOffset][8]; - _indoorList._objects8._y = INDOOR_OBJECT_Y[listOffset][8]; - _indoorList._objects8._frame = mazeObject._frame; - _indoorList._objects8._sprites = mazeObject._sprites; - _indoorList._objects8._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects8._flags |= SPRFLAG_HORIZ_FLIPPED; - } - - // Position 10 - pt = Common::Point(mazePos.x + posOffset[23], mazePos.y + posOffset[215]); - if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[20]) && (!_wo[22] || !_wo[23]) && - (!_wo[20] || !_wo[17]) && (!_wo[23] || !_wo[17]) && !_wo[12] && !_wo[8] && - _indoorList._objects9._frame == -1) { - _indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][9]; - _indoorList._objects9._y = INDOOR_OBJECT_Y[listOffset][9]; - _indoorList._objects9._frame = mazeObject._frame; - _indoorList._objects9._sprites = mazeObject._sprites; - _indoorList._objects9._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects9._flags |= SPRFLAG_HORIZ_FLIPPED; - } - - // Block 11 - pt = Common::Point(mazePos.x + posOffset[29], mazePos.y + posOffset[221]); - if (pt == mazeObject._position && !_wo[27] && !_wo[22] && (!_wo[15] || !_wo[19]) && - (!_wo[15] || !_wo[14]) && (!_wo[14] || !_wo[9]) && (!_wo[19] || !_wo[9]) && - _indoorList._objects10._frame == -1) { - _indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][10]; - _indoorList._objects10._y = INDOOR_OBJECT_Y[listOffset][10]; - _indoorList._objects10._frame = mazeObject._frame; - _indoorList._objects10._sprites = mazeObject._sprites; - _indoorList._objects10._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects10._flags |= SPRFLAG_HORIZ_FLIPPED; - } - - // Block 12 - pt = Common::Point(mazePos.x + posOffset[31], mazePos.y + posOffset[223]); - if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[21]) && (!_wo[22] || !_wo[24]) && - (!_wo[21] || !_wo[19]) && (!_wo[24] || !_wo[19]) && !_wo[14] && !_wo[10] && - _indoorList._objects11._frame == -1) { - _indoorList._objects11._x = INDOOR_OBJECT_X[listOffset][11]; - _indoorList._objects11._y = INDOOR_OBJECT_Y[listOffset][11]; - _indoorList._objects11._frame = mazeObject._frame; - _indoorList._objects11._sprites = mazeObject._sprites; - _indoorList._objects11._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects11._flags |= SPRFLAG_HORIZ_FLIPPED; - } - } -} - -void Interface::setIndoorWallPics() { - // TODO -} - - -void Interface::setOutdoorsMonsters() { - -} - -void Interface::setOutdoorsObjects() { - -} - void Interface::startup() { Screen &screen = *_vm->_screen; loadCharIcons(); @@ -2845,1140 +2308,6 @@ void Interface::setMazeBits() { } } -void Interface::drawIndoors() { - Map &map = *_vm->_map; - int surfaceId; - int idx; - - for (int cellIndex = 0; cellIndex < 25; ++cellIndex) { - map.getCell(DRAW_NUMBERS[cellIndex]); - - DrawStruct &drawStruct = _indoorList[3 + cellIndex]; - drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId]; - - surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; - if (surfaceId == 5 || surfaceId == 12) { - drawStruct._flags = _flipWtr; - drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWtr ? 1 : 0]; - } - else { - drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWall ? 1 : 0]; - drawStruct._flags = _flipWall ? 0 : SPRFLAG_HORIZ_FLIPPED; - } - } - - if (!_wo[27] && !_wo[20] && !_wo[23] && !_wo[12] && !_wo[8] && !_wo[30]) { - if (_wo[39]) - _indoorList._swl_4F4L._frame = 22; - else if (_wo[83]) - _indoorList._swl_4F4L._frame = 46; - } - - if (!_wo[27] && !_wo[22] && !_wo[17] && !_wo[12] && !_wo[8]) { - if (_wo[38]) - _indoorList._swl_4F3L._frame = 20; - else if (_wo[82]) - _indoorList._swl_4F3L._frame = 44; - } - - if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[2] && !_wo[7]) { - if (_wo[37]) - _indoorList._swl_4F2L._frame = 18; - else if (_wo[81]) - _indoorList._swl_4F2L._frame = 42; - } - - if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[6]) { - if (_wo[36]) - _indoorList._swl_4F1L._frame = 16; - else if (_wo[80]) - _indoorList._swl_4F1L._frame = 40; - } - - if (!_wo[27] && !_wo[21] && !_wo[24] && !_wo[14] && !_wo[10] && !_wo[31]) { - if (_wo[43]) - _indoorList._swl_4F4R._frame = 23; - else if (_wo[87]) - _indoorList._swl_4F4R._frame = 47; - } - - if (!_wo[27] && !_wo[22] && !_wo[19] && !_wo[14] && !_wo[10]) { - if (_wo[42]) - _indoorList._swl_4F3R._frame = 21; - else if (_wo[86]) - _indoorList._swl_4F3R._frame = 45; - } - - if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[5] && !_wo[9]) { - if (_wo[41]) - _indoorList._swl_4F2R._frame = 19; - else if (_wo[85]) - _indoorList._swl_4F2R._frame = 43; - } - - if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[6]) { - if (_wo[40]) - _indoorList._swl_4F1R._frame = 17; - else if (_wo[84]) - _indoorList._swl_4F1R._frame = 41; - } - - if (!_wo[25] && !_wo[28] && !_wo[20] && !_wo[11] && - !_wo[16] && !_wo[30] && !_wo[32]) { - if (_wo[88]) - _indoorList._fwl_4F4L._frame = 7; - else if (_wo[78]) - _indoorList._fwl_4F4L._frame = 16; - else if (_wo[148]) - _indoorList._fwl_4F4L._frame = _overallFrame + 1; - else if (_wo[108]) - _indoorList._fwl_4F4L._frame = 8; - else if (_wo[168]) - _indoorList._fwl_4F4L._frame = 10; - else if (_wo[128]) - _indoorList._fwl_4F4L._frame = 9; - else if (_wo[34]) - _indoorList._fwl_4F4L._frame = 0; - else if (_wo[188]) - _indoorList._fwl_4F4L._frame = 15; - else if (_wo[208]) - _indoorList._fwl_4F4L._frame = 14; - else if (_wo[228]) - _indoorList._fwl_4F4L._frame = 6; - else if (_wo[248]) - _indoorList._fwl_4F4L._frame = 11; - else if (_wo[268]) - _indoorList._fwl_4F4L._frame = 12; - else if (_wo[288]) - _indoorList._fwl_4F4L._frame = 13; - } - - if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31] && !_wo[33]) { - if (_wo[93]) - _indoorList._fwl_4F4R._frame = 7; - else if (_wo[79]) - _indoorList._fwl_4F4R._frame = 16; - else if (_wo[153]) - _indoorList._fwl_4F4R._frame = _overallFrame + 1; - else if (_wo[113]) - _indoorList._fwl_4F4R._frame = 8; - else if (_wo[173]) - _indoorList._fwl_4F4R._frame = 10; - else if (_wo[133]) - _indoorList._fwl_4F4R._frame = 9; - else if (_wo[35]) - _indoorList._fwl_4F4R._frame = 0; - else if (_wo[79]) - _indoorList._fwl_4F4R._frame = 15; - else if (_wo[213]) - _indoorList._fwl_4F4R._frame = 14; - else if (_wo[233]) - _indoorList._fwl_4F4R._frame = 6; - else if (_wo[253]) - _indoorList._fwl_4F4R._frame = 11; - else if (_wo[273]) - _indoorList._fwl_4F4R._frame = 12; - else if (_wo[293]) - _indoorList._fwl_4F4R._frame = 13; - } - - if (!_wo[25] && !_wo[28] && !_wo[20] && !_wo[11] && !_wo[16] && !_wo[30]) { - if (_wo[32]) - _indoorList._swl_3F4L._frame = 14; - else if (_wo[76]) - _indoorList._swl_3F4L._frame = 38; - } - - if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31]) { - if (_wo[33]) - _indoorList._fwl_3F1R._frame = 15; - else if (_wo[77]) - _indoorList._swl_3F1R._frame = 39; - } - - if (_wo[28] && _wo[27]) { - } - else if (_wo[28] && _wo[12]) { - } - else if (_wo[28] && _wo[23]) { - } - else if (_wo[28] && _wo[8]) { - } - else if (_wo[25] && _wo[27]) { - } - else if (_wo[25] && _wo[12]) { - } - else if (_wo[25] && _wo[23]) { - } - else if (_wo[25] && _wo[8]) { - } - else if (_wo[11] && _wo[27]) { - } - else if (_wo[11] && _wo[12]) { - } - else if (_wo[11] && _wo[23]) { - } - else if (_wo[11] && _wo[8]) { - } - else if (_wo[17] && _wo[27]) { - } - else if (_wo[17] && _wo[12]) { - } - else if (_wo[17] && _wo[23]) { - } - else if (_wo[17] && _wo[8]) { - } - else if (_wo[20]) { - } - else if (_wo[30]) { - _indoorList._swl_3F3L._frame = 12; - } - else if (_wo[74]) { - _indoorList._swl_3F3L._frame = 36; - } - - if (_wo[29] && _wo[27]) { - } - else if (_wo[29] && _wo[14]) { - } - else if (_wo[29] && _wo[24]) { - } - else if (_wo[29] && _wo[10]) { - } - else if (_wo[26] && _wo[27]) { - } - else if (_wo[26] && _wo[14]) { - } - else if (_wo[26] && _wo[24]) { - } - else if (_wo[26] && _wo[10]) { - } - else if (_wo[13] && _wo[27]) { - } - else if (_wo[13] && _wo[14]) { - } - else if (_wo[13] && _wo[24]) { - } - else if (_wo[13] && _wo[10]) { - } - else if (_wo[19] && _wo[27]) { - } - else if (_wo[19] && _wo[24]) { - } - else if (_wo[19] && _wo[10]) { - } - else if (_wo[21]) { - } - else if (_wo[31]) { - _indoorList._swl_3F2R._frame = 13; - } - else if (_wo[75]) { - _indoorList._swl_3F2R._frame = 37; - } - - if (!_wo[27] && !_wo[20] && !_wo[12] && !_wo[23] && !_wo[8] && !_wo[30]) { - if (_wo[89]) - _indoorList._fwl_4F3L._frame = 7; - else if (_wo[44]) - _indoorList._fwl_4F3L._frame = 16; - else if (_wo[149]) - _indoorList._fwl_4F3L._frame = _overallFrame + 1; - else if (_wo[109]) - _indoorList._fwl_4F3L._frame = 8; - else if (_wo[169]) - _indoorList._fwl_4F3L._frame = 10; - else if (_wo[129]) - _indoorList._fwl_4F3L._frame = 9; - else if (_wo[0]) - _indoorList._fwl_4F3L._frame = 0; - else if (_wo[189]) - _indoorList._fwl_4F3L._frame = 15; - else if (_wo[209]) - _indoorList._fwl_4F3L._frame = 14; - else if (_wo[229]) - _indoorList._fwl_4F3L._frame = 6; - else if (_wo[249]) - _indoorList._fwl_4F3L._frame = 11; - else if (_wo[269]) - _indoorList._fwl_4F3L._frame = 12; - else if (_wo[289]) - _indoorList._fwl_4F3L._frame = 13; - } - - if (_wo[22] && _wo[20]) { - } - else if (_wo[22] && _wo[23]) { - } - else if (_wo[20] && _wo[17]) { - } - else if (_wo[23] && _wo[17]) { - } - else if (_wo[12]) { - } - else if (_wo[8]) { - } - else if (_wo[90]) { - _indoorList._fwl_4F2L._frame = 7; - } - else if (_wo[45]) { - _indoorList._fwl_4F2L._frame = 16; - } - else if (_wo[150]) { - _indoorList._fwl_4F2L._frame = _overallFrame + 1; - } - else if (_wo[110]) { - _indoorList._fwl_4F2L._frame = 8; - } - else if (_wo[170]) { - _indoorList._fwl_4F2L._frame = 10; - } - else if (_wo[130]) { - _indoorList._fwl_4F2L._frame = 9; - } - else if (_wo[1]) { - _indoorList._fwl_4F2L._frame = 0; - } - else if (_wo[190]) { - _indoorList._fwl_4F2L._frame = 15; - } - else if (_wo[210]) { - _indoorList._fwl_4F2L._frame = 14; - } - else if (_wo[230]) { - _indoorList._fwl_4F2L._frame = 6; - } - else if (_wo[250]) { - _indoorList._fwl_4F2L._frame = 11; - } - else if (_wo[270]) { - _indoorList._fwl_4F2L._frame = 12; - } - else if (_wo[290]) { - _indoorList._fwl_4F2L._frame = 13; - } - - if (_wo[15] && _wo[17]) { - } - else if (_wo[15] && _wo[12]) { - } - else if (_wo[12] && _wo[7]) { - } - else if (_wo[17] && _wo[7]) { - } - else if (_wo[91]) { - _indoorList._fwl_4F1L._frame = 7; - } - else if (_wo[46]) { - _indoorList._fwl_4F1L._frame = 16; - } - else if (_wo[151]) { - _indoorList._fwl_4F1L._frame = _overallFrame + 1; - } - else if (_wo[111]) { - _indoorList._fwl_4F1L._frame = 8; - } - else if (_wo[171]) { - _indoorList._fwl_4F1L._frame = 10; - } - else if (_wo[131]) { - _indoorList._fwl_4F1L._frame = 9; - } - else if (_wo[2]) { - _indoorList._fwl_4F1L._frame = 0; - } - else if (_wo[191]) { - _indoorList._fwl_4F1L._frame = 15; - } - else if (_wo[211]) { - _indoorList._fwl_4F1L._frame = 14; - } - else if (_wo[231]) { - _indoorList._fwl_4F1L._frame = 6; - } - else if (_wo[251]) { - _indoorList._fwl_4F1L._frame = 11; - } - else if (_wo[271]) { - _indoorList._fwl_4F1L._frame = 12; - } - else if (_wo[291]) { - _indoorList._fwl_4F1L._frame = 13; - } - - if (!_wo[27] && !_wo[21] && !_wo[14] && !_wo[24] && !_wo[10] && !_wo[31]) { - if (_wo[92]) { - _indoorList._fwl_4F3R._frame = 7; - } - else if (_wo[47]) { - _indoorList._fwl_4F3R._frame = 16; - } - else if (_wo[152]) { - _indoorList._fwl_4F3R._frame = _overallFrame + 1; - } - else if (_wo[112]) { - _indoorList._fwl_4F3R._frame = 8; - } - else if (_wo[172]) { - _indoorList._fwl_4F3R._frame = 10; - } - else if (_wo[132]) { - _indoorList._fwl_4F3R._frame = 9; - } - else if (_wo[3]) { - _indoorList._fwl_4F3R._frame = 0; - } - else if (_wo[192]) { - _indoorList._fwl_4F3R._frame = 15; - } - else if (_wo[212]) { - _indoorList._fwl_4F3R._frame = 14; - } - else if (_wo[232]) { - _indoorList._fwl_4F3R._frame = 6; - } - else if (_wo[252]) { - _indoorList._fwl_4F3R._frame = 11; - } - else if (_wo[272]) { - _indoorList._fwl_4F3R._frame = 12; - } - else if (_wo[292]) { - _indoorList._fwl_4F3R._frame = 13; - } - } - - if (_wo[22] && _wo[21]) { - } - else if (_wo[22] && _wo[24]) { - } - else if (_wo[21] && _wo[19]) { - } - else if (_wo[24] && _wo[19]) { - } - else if (_wo[14] || _wo[10]) { - } - else if (_wo[94]) { - _indoorList._fwl_4F2R._frame = 7; - } - else if (_wo[48]) { - _indoorList._fwl_4F2R._frame = 16; - } - else if (_wo[154]) { - _indoorList._fwl_4F2R._frame = _overallFrame + 1; - } - else if (_wo[114]) { - _indoorList._fwl_4F2R._frame = 8; - } - else if (_wo[174]) { - _indoorList._fwl_4F2R._frame = 10; - } - else if (_wo[134]) { - _indoorList._fwl_4F2R._frame = 9; - } - else if (_wo[4]) { - _indoorList._fwl_4F2R._frame = 0; - } - else if (_wo[194]) { - _indoorList._fwl_4F2R._frame = 15; - } - else if (_wo[214]) { - _indoorList._fwl_4F2R._frame = 14; - } - else if (_wo[234]) { - _indoorList._fwl_4F2R._frame = 6; - } - else if (_wo[254]) { - _indoorList._fwl_4F2R._frame = 11; - } - else if (_wo[274]) { - _indoorList._fwl_4F2R._frame = 12; - } - else if (_wo[294]) { - _indoorList._fwl_4F2R._frame = 13; - } - - if (_wo[15] && _wo[19]) { - } - else if (_wo[15] && _wo[14]) { - } - else if (_wo[14] && _wo[9]) { - } - else if (_wo[19] && _wo[9]) { - } - else if (_wo[95]) { - _indoorList._fwl_4F1R._frame = 7; - } - else if (_wo[49]) { - _indoorList._fwl_4F1R._frame = 16; - } - else if (_wo[155]) { - _indoorList._fwl_4F1R._frame = _overallFrame + 1; - } - else if (_wo[115]) { - _indoorList._fwl_4F1R._frame = 8; - } - else if (_wo[175]) { - _indoorList._fwl_4F1R._frame = 10; - } - else if (_wo[135]) { - _indoorList._fwl_4F1R._frame = 9; - } - else if (_wo[5]) { - _indoorList._fwl_4F1R._frame = 0; - } - else if (_wo[195]) { - _indoorList._fwl_4F1R._frame = 15; - } - else if (_wo[215]) { - _indoorList._fwl_4F1R._frame = 14; - } - else if (_wo[235]) { - _indoorList._fwl_4F1R._frame = 6; - } - else if (_wo[255]) { - _indoorList._fwl_4F1R._frame = 11; - } - else if (_wo[275]) { - _indoorList._fwl_4F1R._frame = 12; - } - else if (_wo[295]) { - _indoorList._fwl_4F1R._frame = 13; - } - - if (_wo[27] || _wo[22] || _wo[15] || _wo[96]) { - } - else if (_wo[50]) { - _indoorList._fwl_4F._frame = 16; - } - else if (_wo[156]) { - _indoorList._fwl_4F._frame = _overallFrame + 1; - } - else if (_wo[116]) { - _indoorList._fwl_4F._frame = 8; - } - else if (_wo[176]) { - _indoorList._fwl_4F._frame = 10; - } - else if (_wo[136]) { - _indoorList._fwl_4F._frame = 9; - } - else if (_wo[6]) { - _indoorList._fwl_4F._frame = 0; - } - else if (_wo[196]) { - _indoorList._fwl_4F._frame = 15; - } - else if (_wo[216]) { - _indoorList._fwl_4F._frame = 14; - } - else if (_wo[236]) { - _indoorList._fwl_4F._frame = 6; - } - else if (_wo[256]) { - _indoorList._fwl_4F._frame = 11; - } - else if (_wo[276]) { - _indoorList._fwl_4F._frame = 12; - } - else if (_wo[296]) { - _indoorList._fwl_4F._frame = 13; - } - - if (!_wo[27] && !_wo[22] && !_wo[15]) { - if (_wo[7]) - _indoorList._swl_3F1L._frame = 8; - else if (_wo[51]) - _indoorList._swl_3F1L._frame = 32; - } - - if (_wo[22] && _wo[23]) { - } - else if (_wo[22] && _wo[20]) { - } - else if (_wo[17] && _wo[23]) { - } - else if (_wo[17] && _wo[20]) { - } - else if (_wo[8]) { - _indoorList._swl_3F2L._frame = 10; - } - else if (_wo[52]) { - _indoorList._swl_3F2L._frame = 34; - } - - if (_wo[27] || _wo[22] || _wo[15]) { - } - else if (_wo[9]) { - _indoorList._swl_3F4R._frame = 9; - } - else if (_wo[53]) { - _indoorList._swl_3F4R._frame = 33; - } - - if (_wo[22] && _wo[24]) { - } - else if (_wo[22] && _wo[21]) { - } - else if (_wo[19] && _wo[24]) { - } - else if (_wo[19] && _wo[21]) { - } - else if (_wo[14]) { - } - else if (_wo[10]) { - _indoorList._swl_3F3R._frame = 11; - } - else if (_wo[54]) { - _indoorList._swl_3F3R._frame = 35; - } - - if (_wo[25] || _wo[28] || _wo[20] || _wo[16]) { - } - else if (_wo[97]) { - _indoorList._fwl_3F2L._frame = 24; - } - else if (_wo[55]) { - _indoorList._fwl_3F2L._frame = 33; - } - else if (_wo[137]) { - _indoorList._fwl_3F2L._frame = 26; - } - else if (_wo[157]) { - _indoorList._fwl_3F2L._frame = _overallFrame + 18; - } - else if (_wo[117]) { - _indoorList._fwl_3F2L._frame = 25; - } - else if (_wo[177]) { - _indoorList._fwl_3F2L._frame = 27; - } - else if (_wo[11]) { - _indoorList._fwl_3F2L._frame = 17; - } - else if (_wo[197]) { - _indoorList._fwl_3F2L._frame = 32; - } - else if (_wo[217]) { - _indoorList._fwl_3F2L._frame = 31; - } - else if (_wo[237]) { - _indoorList._fwl_3F2L._frame = 23; - } - else if (_wo[257]) { - _indoorList._fwl_3F2L._frame = 28; - } - else if (_wo[277]) { - _indoorList._fwl_3F2L._frame = 29; - } - else if (_wo[297]) { - _indoorList._fwl_3F2L._frame = 30; - } - - if (_wo[22] && _wo[23]) { - } - else if (_wo[22] && _wo[20]) { - } - else if (_wo[23] && _wo[17]) { - } - else if (_wo[20] && _wo[17]) { - } - else if (_wo[98]) { - _indoorList._fwl_3F1L._frame = 24; - } - else if (_wo[56]) { - _indoorList._fwl_3F1L._frame = 33; - } - else if (_wo[178]) { - _indoorList._fwl_3F1L._frame = 27; - } - else if (_wo[118]) { - _indoorList._fwl_3F1L._frame = 25; - } - else if (_wo[158]) { - _indoorList._fwl_3F1L._frame = _overallFrame + 18; - } - else if (_wo[138]) { - _indoorList._fwl_3F1L._frame = 26; - } - else if (_wo[12]) { - _indoorList._fwl_3F1L._frame = 17; - } - else if (_wo[198]) { - _indoorList._fwl_3F1L._frame = 32; - } - else if (_wo[218]) { - _indoorList._fwl_3F1L._frame = 31; - } - else if (_wo[238]) { - _indoorList._fwl_3F1L._frame = 23; - } - else if (_wo[258]) { - _indoorList._fwl_3F1L._frame = 28; - } - else if (_wo[278]) { - _indoorList._fwl_3F1L._frame = 29; - } - else if (_wo[298]) { - _indoorList._fwl_3F1L._frame = 30; - } - - if (_wo[26] || _wo[29] || _wo[21] || _wo[18]) { - } - else if (_wo[99]) { - _indoorList._fwl_3F2R._frame = 24; - } - else if (_wo[57]) { - _indoorList._fwl_3F2R._frame = 33; - } - else if (_wo[139]) { - _indoorList._fwl_3F2R._frame = 26; - } - else if (_wo[159]) { - _indoorList._fwl_3F2R._frame = _overallFrame + 18; - } - else if (_wo[119]) { - _indoorList._fwl_3F2R._frame = 25; - } - else if (_wo[179]) { - _indoorList._fwl_3F2R._frame = 27; - } - else if (_wo[13]) { - _indoorList._fwl_3F2R._frame = 17; - } - else if (_wo[199]) { - _indoorList._fwl_3F2R._frame = 32; - } - else if (_wo[219]) { - _indoorList._fwl_3F2R._frame = 31; - } - else if (_wo[239]) { - _indoorList._fwl_3F2R._frame = 23; - } - else if (_wo[259]) { - _indoorList._fwl_3F2R._frame = 28; - } - else if (_wo[279]) { - _indoorList._fwl_3F2R._frame = 29; - } - else if (_wo[299]) { - _indoorList._fwl_3F2R._frame = 30; - } - - if (_wo[22] && _wo[24]) { - } - else if (_wo[22] && _wo[21]) { - } - else if (_wo[24] && _wo[19]) { - } - else if (_wo[21] && _wo[19]) { - } - else if (_wo[100]) { - _indoorList._fwl_3F1R._frame = 24; - } - else if (_wo[58]) { - _indoorList._fwl_3F1R._frame = 33; - } - else if (_wo[140]) { - _indoorList._fwl_3F1R._frame = 26; - } - else if (_wo[160]) { - _indoorList._fwl_3F1R._frame = _overallFrame + 18; - } - else if (_wo[120]) { - _indoorList._fwl_3F1R._frame = 25; - } - else if (_wo[180]) { - _indoorList._fwl_3F1R._frame = 27; - } - else if (_wo[14]) { - _indoorList._fwl_3F1R._frame = 17; - } - else if (_wo[200]) { - _indoorList._fwl_3F1R._frame = 32; - } - else if (_wo[220]) { - _indoorList._fwl_3F1R._frame = 31; - } - else if (_wo[240]) { - _indoorList._fwl_3F1R._frame = 23; - } - else if (_wo[260]) { - _indoorList._fwl_3F1R._frame = 28; - } - else if (_wo[280]) { - _indoorList._fwl_3F1R._frame = 29; - } - else if (_wo[300]) { - _indoorList._fwl_3F1R._frame = 30; - } - - if (_wo[22] || _wo[27]) { - } - else if (_wo[101]) { - _indoorList._fwl_3F._frame = 24; - } - else if (_wo[59]) { - _indoorList._fwl_3F._frame = 33; - } - else if (_wo[141]) { - _indoorList._fwl_3F._frame = 26; - } - else if (_wo[161]) { - _indoorList._fwl_3F._frame = _overallFrame + 18; - } - else if (_wo[121]) { - _indoorList._fwl_3F._frame = 25; - } - else if (_wo[181]) { - _indoorList._fwl_3F._frame = 27; - } - else if (_wo[15]) { - _indoorList._fwl_3F._frame = 17; - } - else if (_wo[201]) { - _indoorList._fwl_3F._frame = 32; - } - else if (_wo[221]) { - _indoorList._fwl_3F._frame = 31; - } - else if (_wo[241]) { - _indoorList._fwl_3F._frame = 23; - } - else if (_wo[261]) { - _indoorList._fwl_3F._frame = 28; - } - else if (_wo[281]) { - _indoorList._fwl_3F._frame = 29; - } - else if (_wo[301]) { - _indoorList._fwl_3F._frame = 30; - } - - if (_wo[25] || _wo[28] || _wo[20]) { - } - else if (_wo[16]) { - _indoorList._swl_2F2L._frame = 6; - } - else if (_wo[60]) { - _indoorList._swl_2F2L._frame = 30; - } - - if (_wo[27] || _wo[22]) { - } - else if (_wo[17]) { - _indoorList._swl_2F1L._frame = 4; - } - else if (_wo[61]) { - _indoorList._swl_2F1L._frame = 28; - } - - if (_wo[26] || _wo[29] || _wo[21]) { - } - else if (_wo[18]) { - _indoorList._swl_2F2R._frame = 7; - } - else if (_wo[62]) { - _indoorList._swl_2F2R._frame = 31; - } - - if (_wo[27] || _wo[22]) { - } - else if (_wo[19]) { - _indoorList._swl_2F1R._frame = 5; - } - else if (_wo[63]) { - _indoorList._swl_2F1R._frame = 29; - } - - if (_wo[27] && _wo[25]) { - } - else if (_wo[27] && _wo[28]) { - } - else if (_wo[23] & _wo[25]) { - } - else if (_wo[23] && _wo[28]) { - } - else if (_wo[102]) { - _indoorList._fwl_2F1L._frame = 7; - } - else if (_wo[64]) { - _indoorList._fwl_2F1L._frame = 16; - } - else if (_wo[182]) { - _indoorList._fwl_2F1L._frame = 10; - } - else if (_wo[122]) { - _indoorList._fwl_2F1L._frame = 8; - } - else if (_wo[142]) { - _indoorList._fwl_2F1L._frame = 9; - } - else if (_wo[162]) { - _indoorList._fwl_2F1L._frame = _overallFrame + 1; - } - else if (_wo[20]) { - _indoorList._fwl_2F1L._frame = 0; - } - else if (_wo[202]) { - _indoorList._fwl_2F1L._frame = 15; - } - else if (_wo[222]) { - _indoorList._fwl_2F1L._frame = 14; - } - else if (_wo[242]) { - _indoorList._fwl_2F1L._frame = 6; - } - else if (_wo[262]) { - _indoorList._fwl_2F1L._frame = 11; - } - else if (_wo[282]) { - _indoorList._fwl_2F1L._frame = 12; - } - else if (_wo[302]) { - _indoorList._fwl_2F1L._frame = 13; - } - - if (_wo[27] && _wo[26]) { - } - else if (_wo[27] && _wo[29]) { - } - else if (_wo[24] && _wo[26]) { - } - else if (_wo[24] && _wo[29]) { - } - else if (_wo[103]) { - _indoorList._fwl_2F1R._frame = 7; - } - else if (_wo[65]) { - _indoorList._fwl_2F1R._frame = 16; - } - else if (_wo[183]) { - _indoorList._fwl_2F1R._frame = 10; - } - else if (_wo[123]) { - _indoorList._fwl_2F1R._frame = 8; - } - else if (_wo[143]) { - _indoorList._fwl_2F1R._frame = 9; - } - else if (_wo[163]) { - _indoorList._fwl_2F1R._frame = _overallFrame + 1; - } - else if (_wo[21]) { - _indoorList._fwl_2F1R._frame = 0; - } - else if (_wo[203]) { - _indoorList._fwl_2F1R._frame = 15; - } - else if (_wo[223]) { - _indoorList._fwl_2F1R._frame = 14; - } - else if (_wo[243]) { - _indoorList._fwl_2F1R._frame = 6; - } - else if (_wo[263]) { - _indoorList._fwl_2F1R._frame = 11; - } - else if (_wo[283]) { - _indoorList._fwl_2F1R._frame = 12; - } - else if (_wo[303]) { - _indoorList._fwl_2F1R._frame = 13; - } - - if (_wo[27]) { - - } - else if (_wo[104]) { - _indoorList._fwl_2F._frame = 7; - } - else if (_wo[66]) { - _indoorList._fwl_2F._frame = 16; - } - else if (_wo[184]) { - _indoorList._fwl_2F._frame = 10; - } - else if (_wo[124]) { - _indoorList._fwl_2F._frame = 8; - } - else if (_wo[144]) { - _indoorList._fwl_2F._frame = 9; - } - else if (_wo[164]) { - _indoorList._fwl_2F._frame = _overallFrame + 1; - } - else if (_wo[22]) { - _indoorList._fwl_2F._frame = 0; - } - else if (_wo[204]) { - _indoorList._fwl_2F._frame = 15; - } - else if (_wo[224]) { - _indoorList._fwl_2F._frame = 14; - } - else if (_wo[244]) { - _indoorList._fwl_2F._frame = 6; - } - else if (_wo[264]) { - _indoorList._fwl_2F._frame = 11; - } - else if (_wo[284]) { - _indoorList._fwl_2F._frame = 12; - } - else if (_wo[304]) { - _indoorList._fwl_2F._frame = 13; - } - - if (_wo[27]) { - } - else if (_wo[23]) { - _indoorList._swl_1F1L._frame = 2; - } - else if (_wo[67]) { - _indoorList._swl_1F1L._frame = 26; - } - - if (_wo[27]) { - } - else if (_wo[24]) { - _indoorList._swl_1F1R._frame = 3; - } - else if (_wo[68]) { - _indoorList._swl_1F1R._frame = 27; - } - - if (_wo[28]) { - } - else if (_wo[105] || _wo[25] || _wo[165] || _wo[125] || _wo[185] || _wo[145]) { - _indoorList._fwl_1F1L._frame = 0; - _indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl1; - } - else if (_wo[69]) { - _indoorList._fwl_1F1L._frame = 9; - _indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl2; - } - - if (_wo[29]) { - } - else if (_wo[106] || _wo[26] || _wo[166] || _wo[126] || _wo[186] || _wo[146]) { - _indoorList._fwl_1F._frame = 0; - _indoorList._fwl_1F._sprites = &map._wallSprites._fwl1; - } - else if (_wo[70]) { - _indoorList._fwl_1F._frame = 9; - _indoorList._fwl_1F._sprites = &map._wallSprites._fwl2; - } - - if (_wo[107]) { - _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - if (_vm->_openDoor) - _indoorList._fwl_1F1R._frame = 0; - else - _indoorList._fwl_1F1R._frame = map.mazeData()._wallKind ? 1 : 10; - } - else if (_wo[71]) { - _indoorList._fwl_1F1R._frame = 9; - _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[167]) { - _indoorList._fwl_1F1R._frame = _overallFrame + 1; - _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[127]) { - _indoorList._fwl_1F1R._frame = 1; - _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[147]) { - _indoorList._fwl_1F1R._frame = 2; - _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[187]) { - _indoorList._fwl_1F1R._frame = 3; - _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[27]) { - _indoorList._fwl_1F1R._frame = 0; - _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1; - } - else if (_wo[207]) { - _indoorList._fwl_1F1R._frame = 8; - _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[227]) { - _indoorList._fwl_1F1R._frame = 7; - _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[247]) { - _indoorList._fwl_1F1R._frame = 6; - _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1; - } - else if (_wo[267]) { - _indoorList._fwl_1F1R._frame = 4; - _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[287]) { - _indoorList._fwl_1F1R._frame = 5; - _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[307]) { - _indoorList._fwl_1F1R._frame = 6; - _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - - if (_wo[28]) { - _indoorList._swl_0F1L._frame = 0; - } - else if (_wo[72]) { - _indoorList._swl_0F1L._frame = 24; - } - - if (_wo[29]) { - _indoorList._swl_0F1R._frame = 1; - } - else if (_wo[73]) { - _indoorList._swl_0F1R._frame = 25; - } - - map.cellFlagLookup(_vm->_party._mazePosition); - - // WORKAROUND: Original did an array lookup on _skySprites. - // Was this a feature for multiple skys that was abandoned? - _indoorList[0]._sprites = &map._skySprites; - _indoorList[0]._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0; - - if (_vm->_openDoor) { - Common::Point pt( - _vm->_party._mazePosition.x + SCREEN_POSITIONING_X[ - _vm->_party._mazeDirection][_vm->_party._mazePosition.x], - _vm->_party._mazePosition.y + SCREEN_POSITIONING_Y[ - _vm->_party._mazeDirection][_vm->_party._mazePosition.y] - ); - map.cellFlagLookup(pt); - - _indoorList._sky._sprites = &map._skySprites; - } else { - _indoorList._sky._sprites = _indoorList[0]._sprites; - } - - _indoorList._sky._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0; - _indoorList._ground._flags = _flipGround ? SPRFLAG_HORIZ_FLIPPED : 0; - _indoorList._horizon._frame = 7; - - // Finally draw the darn indoor scene - _vm->_screen->_windows[3].drawList(&_indoorList[0], _indoorList.size()); - - // Check for any character shooting - _isShooting = false; - for (int i = 0; i < _vm->_party._partyCount; ++i) { - if (_vm->_combat->_shooting[i]) - _isShooting = true; - } - - _charsShooting = _isShooting; - - // TODO -} - void Interface::updateAutoMap() { // TODO } diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index f84885f307..4667592b20 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -25,6 +25,7 @@ #include "common/scummsys.h" #include "xeen/dialogs.h" +#include "xeen/interface_map.h" #include "xeen/party.h" #include "xeen/screen.h" @@ -32,55 +33,7 @@ namespace Xeen { class XeenEngine; -class OutdoorDrawList { -public: - DrawStruct _data[132]; - DrawStruct &_skySprite; - DrawStruct &_groundSprite; -public: - OutdoorDrawList(); - - DrawStruct &operator[](int idx) { - assert(idx < size()); - return _data[idx]; - } - - int size() const { return 132; } -}; - -class IndoorDrawList { -public: - DrawStruct _data[170]; - DrawStruct &_sky; - DrawStruct &_ground; - DrawStruct &_horizon; - DrawStruct &_swl_0F1R, _swl_0F1L, _swl_1F1R, _swl_1F1L, - _swl_2F2R, _swl_2F1R, _swl_2F1L, _swl_2F2L, - _swl_3F1R, _swl_3F2R, _swl_3F3R, _swl_3F4R, - _swl_3F1L, _swl_3F2L, _swl_3F3L, _swl_3F4L, - _swl_4F4R, _swl_4F3R, _swl_4F2R, _swl_4F1R, - _swl_4F1L, _swl_4F2L, _swl_4F3L, _swl_4F4L; - DrawStruct &_fwl_4F4R, _fwl_4F3R, _fwl_4F2R, _fwl_4F1R, - _fwl_4F, _fwl_4F1L, _fwl_4F2L, _fwl_4F3L, _fwl_4F4L; - DrawStruct &_fwl_2F1R, _fwl_2F, _fwl_2F1L, _fwl_3F2R, - _fwl_3F1R, _fwl_3F, _fwl_3F1L, _fwl_3F2L; - DrawStruct &_fwl_1F, _fwl_1F1R, _fwl_1F1L; - DrawStruct &_objects0, _objects1, _objects2, _objects3; - DrawStruct &_objects4, _objects5, _objects6, _objects7; - DrawStruct &_objects8, _objects9, _objects10, _objects11; -public: - IndoorDrawList(); - - DrawStruct &operator[](int idx) { - assert(idx < size()); - return _data[idx]; - } - - int size() const { return 170; } -}; - - -class Interface: public ButtonContainer { +class Interface: public ButtonContainer, public InterfaceMap { private: XeenEngine *_vm; SpriteResource _dseFace; @@ -115,26 +68,17 @@ private: Common::String _interfaceText; int _hiliteChar; int _intrIndex1; - bool _flipWtr; - bool _flipWall; - bool _flipSky; - bool _flipGround; bool _flag1; int _animCounter; bool _isAnimReset; - bool _charsShooting; byte _tillMove; - int _objNumber; - byte _wp[20]; - byte _wo[308]; bool _thinWall; int _overallFrame; - bool _isShooting; - - void loadSprites(); void initDrawStructs(); + void loadSprites(); + void assembleBorder(); void setupBackground(); @@ -149,18 +93,6 @@ private: void animate3d(); - void setIndoorsMonsters(); - - void setIndoorObjects(); - - void setIndoorWallPics(); - - void drawIndoors(); - - void setOutdoorsMonsters(); - - void setOutdoorsObjects(); - void moveMonsters(); void setMainButtons(); diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp new file mode 100644 index 0000000000..d88f9421ed --- /dev/null +++ b/engines/xeen/interface_map.cpp @@ -0,0 +1,1704 @@ +/* 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 "xeen/interface.h" +#include "xeen/dialogs_error.h" +#include "xeen/resources.h" +#include "xeen/xeen.h" + +namespace Xeen { + +OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]) { + _data[0] = DrawStruct(0, 8, 8); + _data[1] = DrawStruct(1, 8, 25); + _data[2] = DrawStruct(0, 8, 67); + _data[3] = DrawStruct(0, 8, 67); + _data[4] = DrawStruct(0, 38, 67); + _data[5] = DrawStruct(0, 84, 67); + _data[6] = DrawStruct(0, 134, 67); + _data[7] = DrawStruct(0, 117, 67); + _data[8] = DrawStruct(0, 117, 67); + _data[9] = DrawStruct(0, 103, 67); + _data[10] = DrawStruct(0, 8, 73); + _data[11] = DrawStruct(0, 8, 73); + _data[12] = DrawStruct(0, 30, 73); + _data[13] = DrawStruct(0, 181, 73); + _data[14] = DrawStruct(0, 154, 73); + _data[15] = DrawStruct(0, 129, 73); + _data[16] = DrawStruct(0, 87, 73); + _data[17] = DrawStruct(0, 8, 81); + _data[18] = DrawStruct(0, 8, 81); + _data[19] = DrawStruct(0, 202, 81); + _data[20] = DrawStruct(0, 145, 81); + _data[21] = DrawStruct(0, 63, 81); + _data[22] = DrawStruct(0, 8, 93); + _data[23] = DrawStruct(0, 169, 93); + _data[24] = DrawStruct(0, 31, 93); + _data[25] = DrawStruct(0, 8, 109); + _data[26] = DrawStruct(0, 201, 109); + _data[27] = DrawStruct(0, 8, 109); + _data[28] = DrawStruct(1, 65472, 61, 14, SPRFLAG_2000); + _data[29] = DrawStruct(1, 65496, 61, 14, 0); + _data[30] = DrawStruct(1, 65520, 61, 14, 0); + _data[31] = DrawStruct(1, 8, 61, 14, 0); + _data[32] = DrawStruct(1, 128, 61, 14, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000); + _data[33] = DrawStruct(1, 104, 61, 14, SPRFLAG_HORIZ_FLIPPED); + _data[34] = DrawStruct(1, 80, 61, 14, SPRFLAG_HORIZ_FLIPPED); + _data[35] = DrawStruct(1, 56, 61, 14, SPRFLAG_HORIZ_FLIPPED); + _data[36] = DrawStruct(1, 32, 61, 14, 0); + _data[37] = DrawStruct(0, 65527, 61, 14, 0); + _data[38] = DrawStruct(0, 65478, 61, 14, 0); + _data[39] = DrawStruct(0, 40, 61, 14, 0); + _data[40] = DrawStruct(0, 65454, 61, 14, 0); + _data[41] = DrawStruct(0, 64, 61, 14, 0); + _data[42] = DrawStruct(0, 65495, 61, 14, 0); + _data[43] = DrawStruct(0, 65510, 61, 14, 0); + _data[44] = DrawStruct(0, 65502, 61, 14, 0); + _data[45] = DrawStruct(0, 65520, 61, 14, 0); + _data[46] = DrawStruct(0, 23, 61, 14, 0); + _data[47] = DrawStruct(0, 16, 61, 14, 0); + _data[48] = DrawStruct(0, 65478, 61, 14, 0); + _data[49] = DrawStruct(0, 40, 61, 14, 0); + _data[50] = DrawStruct(0, 65519, 61, 14, 0); + _data[51] = DrawStruct(0, 65535, 58, 14, 0); + _data[52] = DrawStruct(0, 65527, 58, 14, 0); + _data[53] = DrawStruct(0, 72, 58, 12, 0); + _data[54] = DrawStruct(0, 72, 58, 12, SPRFLAG_HORIZ_FLIPPED); + _data[55] = DrawStruct(0, 69, 63, 12, 0); + _data[56] = DrawStruct(0, 75, 63, 12, SPRFLAG_HORIZ_FLIPPED); + _data[57] = DrawStruct(0, 73, 53, 12, 0); + _data[58] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED); + _data[59] = DrawStruct(0, 80, 57, 12, 0); + _data[60] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED); + _data[61] = DrawStruct(2, 65525, 54, 8, 0); + _data[62] = DrawStruct(1, 65515, 54, 11, 0); + _data[63] = DrawStruct(2, 165, 54, 8, SPRFLAG_HORIZ_FLIPPED); + _data[64] = DrawStruct(1, 86, 54, 11, SPRFLAG_HORIZ_FLIPPED); + _data[65] = DrawStruct(1, 33, 54, 11, 0); + _data[66] = DrawStruct(0, 65528, 54, 12, 0); + _data[67] = DrawStruct(0, 65463, 54, 12, 0); + _data[68] = DrawStruct(0, 57, 54, 12, 0); + _data[69] = DrawStruct(0, 65471, 54, 12, 0); + _data[70] = DrawStruct(0, 65455, 54, 12, 0); + _data[71] = DrawStruct(0, 49, 54, 12, 0); + _data[72] = DrawStruct(0, 65, 54, 12, 0); + _data[73] = DrawStruct(0, 65512, 54, 12, 0); + _data[74] = DrawStruct(0, 9, 50, 12, 0); + _data[75] = DrawStruct(0, 65528, 50, 12, 0); + _data[76] = DrawStruct(0, 72, 53, 8, 0); + _data[77] = DrawStruct(0, 72, 53, 8, SPRFLAG_HORIZ_FLIPPED); + _data[78] = DrawStruct(0, 77, 58, 8, 0); + _data[79] = DrawStruct(0, 67, 58, 8, SPRFLAG_HORIZ_FLIPPED); + _data[80] = DrawStruct(0, 81, 47, 8, 0); + _data[81] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED); + _data[82] = DrawStruct(0, 94, 52, 8, 0); + _data[83] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED); + _data[84] = DrawStruct(2, 8, 40); + _data[85] = DrawStruct(2, 146, 40, 0, SPRFLAG_HORIZ_FLIPPED); + _data[86] = DrawStruct(1, 32, 40, 6, 0); + _data[87] = DrawStruct(0, 65529, 30, 7, 0); + _data[88] = DrawStruct(0, 65424, 30, 7, SPRFLAG_2000); + _data[89] = DrawStruct(0, 98, 30, 7, SPRFLAG_2000); + _data[90] = DrawStruct(0, 65424, 30, 8, SPRFLAG_2000); + _data[91] = DrawStruct(0, 98, 30, 8, SPRFLAG_2000); + _data[92] = DrawStruct(0, 65498, 30, 8, 0); + _data[93] = DrawStruct(0, 25, 30, 8, 0); + _data[94] = DrawStruct(0, 65529, 30, 8, 0); + _data[95] = DrawStruct(0, 72, 48, 4, 0); + _data[96] = DrawStruct(0, 72, 48, 4, SPRFLAG_HORIZ_FLIPPED); + _data[97] = DrawStruct(0, 85, 53, 4, 0); + _data[98] = DrawStruct(0, 59, 53, 4, SPRFLAG_HORIZ_FLIPPED); + _data[99] = DrawStruct(0, 89, 41, 4, 0); + _data[100] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED); + _data[101] = DrawStruct(0, 106, 47, 4, 0); + _data[102] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED); + _data[103] = DrawStruct(0, 8, 24); + _data[104] = DrawStruct(0, 169, 24, 0, SPRFLAG_HORIZ_FLIPPED); + _data[105] = DrawStruct(1, 32, 24); + _data[106] = DrawStruct(0, 65513, 40, 0, SPRFLAG_2000); + _data[107] = DrawStruct(0, 200, 40, 0, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000); + _data[108] = DrawStruct(0, 8, 47); + _data[109] = DrawStruct(0, 169, 47, 0, SPRFLAG_HORIZ_FLIPPED); + _data[110] = DrawStruct(1, 65480, 65532, 32768, SPRFLAG_4000 | SPRFLAG_2000); + _data[111] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[112] = DrawStruct(0, 65469, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[113] = DrawStruct(0, 44, 73); + _data[114] = DrawStruct(0, 44, 73); + _data[115] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[116] = DrawStruct(0, 169, 73); + _data[117] = DrawStruct(0, 169, 73); + _data[118] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[119] = DrawStruct(0, 110, 73); + _data[120] = DrawStruct(0, 110, 73); + _data[121] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[122] = DrawStruct(0, 110, 73); + _data[123] = DrawStruct(0, 110, 73); + _data[124] = DrawStruct(0, 72, 43); + _data[125] = DrawStruct(0, 72, 43, 0, SPRFLAG_HORIZ_FLIPPED); + _data[126] = DrawStruct(0, 93, 48); + _data[127] = DrawStruct(0, 51, 48, 0, SPRFLAG_HORIZ_FLIPPED); + _data[128] = DrawStruct(0, 97, 36); + _data[129] = DrawStruct(0, 47, 36, 0, SPRFLAG_HORIZ_FLIPPED); + _data[130] = DrawStruct(0, 118, 42); + _data[131] = DrawStruct(0, 26, 42, 0, SPRFLAG_HORIZ_FLIPPED); +} + +/*------------------------------------------------------------------------*/ + +IndoorDrawList::IndoorDrawList() : + _sky(_data[1]), _ground(_data[2]), _horizon(_data[28]), + _swl_0F1R(_data[ 46]), _swl_0F1L(_data[44]), _swl_1F1R(_data[134]), + _swl_1F1L(_data[133]), _swl_2F2R(_data[110]), _swl_2F1R(_data[109]), + _swl_2F1L(_data[108]), _swl_2F2L(_data[107]), _swl_3F1R(_data[ 78]), + _swl_3F2R(_data[ 77]), _swl_3F3R(_data[ 76]), _swl_3F4R(_data[ 75]), + _swl_3F1L(_data[ 74]), _swl_3F2L(_data[ 73]), _swl_3F3L(_data[ 72]), + _swl_3F4L(_data[ 71]), _swl_4F4R(_data[ 33]), _swl_4F3R(_data[ 34]), + _swl_4F2R(_data[ 35]), _swl_4F1R(_data[ 36]), _swl_4F1L(_data[ 32]), + _swl_4F2L(_data[ 31]), _swl_4F3L(_data[ 30]), _swl_4F4L(_data[ 29]), + _fwl_4F4R(_data[ 45]), _fwl_4F3R(_data[ 44]), _fwl_4F2R(_data[ 43]), + _fwl_4F1R(_data[ 42]), _fwl_4F( _data[ 41]), _fwl_4F1L(_data[ 40]), + _fwl_4F2L(_data[ 39]), _fwl_4F3L(_data[ 38]), _fwl_4F4L(_data[ 37]), + _fwl_2F1R(_data[121]), _fwl_2F( _data[120]), _fwl_2F1L(_data[119]), + _fwl_3F2R(_data[ 91]), _fwl_3F1R(_data[ 90]), _fwl_3F( _data[ 89]), + _fwl_3F1L(_data[ 88]), _fwl_3F2L(_data[ 87]), _fwl_1F( _data[147]), + _fwl_1F1R(_data[145]), _fwl_1F1L(_data[143]), + _objects0(_data[149]), _objects1(_data[125]), _objects2(_data[126]), + _objects3(_data[127]), _objects4(_data[97]), _objects5(_data[98]), + _objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]), + _objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]) { + // Setup draw structure positions + _data[0] = DrawStruct(0, 8, 8); + _data[1] = DrawStruct(1, 8, 25); + _data[2] = DrawStruct(0, 8, 67); + _data[3] = DrawStruct(0, 8, 67); + _data[4] = DrawStruct(0, 38, 67); + _data[5] = DrawStruct(0, 84, 67); + _data[6] = DrawStruct(0, 134, 67); + _data[7] = DrawStruct(0, 117, 67); + _data[8] = DrawStruct(0, 117, 67); + _data[9] = DrawStruct(0, 103, 67); + _data[10] = DrawStruct(0, 8, 73); + _data[11] = DrawStruct(0, 8, 73); + _data[12] = DrawStruct(0, 30, 73); + _data[13] = DrawStruct(0, 181, 73); + _data[14] = DrawStruct(0, 154, 73); + _data[15] = DrawStruct(0, 129, 73); + _data[16] = DrawStruct(0, 87, 73); + _data[17] = DrawStruct(0, 8, 81); + _data[18] = DrawStruct(0, 8, 81); + _data[19] = DrawStruct(0, 202, 81); + _data[20] = DrawStruct(0, 145, 81); + _data[21] = DrawStruct(0, 63, 81); + _data[22] = DrawStruct(0, 8, 93); + _data[23] = DrawStruct(0, 169, 93); + _data[24] = DrawStruct(0, 31, 93); + _data[25] = DrawStruct(0, 8, 109); + _data[26] = DrawStruct(0, 201, 109); + _data[27] = DrawStruct(0, 8, 109); + _data[28] = DrawStruct(7, 8, 64); + _data[29] = DrawStruct(22, 32, 60); + _data[30] = DrawStruct(20, 56, 60); + _data[31] = DrawStruct(18, 80, 60); + _data[32] = DrawStruct(16, 104, 60); + _data[33] = DrawStruct(23, 152, 60, 0, SPRFLAG_HORIZ_FLIPPED); + _data[34] = DrawStruct(21, 144, 60, 0, SPRFLAG_HORIZ_FLIPPED); + _data[35] = DrawStruct(19, 131, 60, 0, SPRFLAG_HORIZ_FLIPPED); + _data[36] = DrawStruct(17, 120, 60, 0, SPRFLAG_HORIZ_FLIPPED); + _data[37] = DrawStruct(14, 8, 60); + _data[38] = DrawStruct(12, 32, 60); + _data[39] = DrawStruct(10, 56, 60); + _data[40] = DrawStruct(14, 80, 60); + _data[41] = DrawStruct(14, 104, 60); + _data[42] = DrawStruct(14, 128, 60); + _data[43] = DrawStruct(14, 152, 60); + _data[44] = DrawStruct(8, 176, 60); + _data[45] = DrawStruct(8, 200, 60); + _data[46] = DrawStruct(0, 65472, 61, 14, 0); + _data[47] = DrawStruct(0, 65496, 61, 14, 0); + _data[48] = DrawStruct(0, 65520, 61, 14, 0); + _data[49] = DrawStruct(0, 8, 61, 14, 0); + _data[50] = DrawStruct(0, 32, 61, 14, 0); + _data[51] = DrawStruct(0, 56, 61, 14, 0); + _data[52] = DrawStruct(0, 80, 61, 14, 0); + _data[53] = DrawStruct(0, 104, 61, 14, 0); + _data[54] = DrawStruct(0, 128, 61, 14, 0); + _data[55] = DrawStruct(0, 65527, 58, 14, 0); + _data[56] = DrawStruct(0, 65502, 58, 14, 0); + _data[57] = DrawStruct(0, 16, 58, 14, 0); + _data[58] = DrawStruct(0, 65478, 58, 14, 0); + _data[59] = DrawStruct(0, 40, 58, 14, 0); + _data[60] = DrawStruct(0, 65495, 58, 14, 0); + _data[61] = DrawStruct(0, 65510, 58, 14, 0); + _data[62] = DrawStruct(0, 65502, 58, 14, 0); + _data[63] = DrawStruct(0, 65520, 58, 14, 0); + _data[64] = DrawStruct(0, 23, 58, 14, 0); + _data[65] = DrawStruct(0, 16, 58, 14, 0); + _data[66] = DrawStruct(0, 65478, 58, 14, 0); + _data[67] = DrawStruct(0, 40, 58, 14, 0); + _data[68] = DrawStruct(0, 65519, 58, 14, 0); + _data[69] = DrawStruct(0, 65535, 58, 14, 0); + _data[70] = DrawStruct(0, 65527, 58, 14, 0); + _data[71] = DrawStruct(14, 8, 58); + _data[72] = DrawStruct(12, 8, 55); + _data[73] = DrawStruct(10, 32, 52); + _data[74] = DrawStruct(14, 88, 52); + _data[75] = DrawStruct(14, 128, 52, 0, SPRFLAG_HORIZ_FLIPPED); + _data[76] = DrawStruct(14, 152, 52, 0, SPRFLAG_HORIZ_FLIPPED); + _data[77] = DrawStruct(0, 176, 55, 0, SPRFLAG_HORIZ_FLIPPED); + _data[78] = DrawStruct(0, 200, 58, 0, SPRFLAG_HORIZ_FLIPPED); + _data[79] = DrawStruct(0, 72, 58, 12, 0); + _data[80] = DrawStruct(0, 72, 58, 12, SPRFLAG_HORIZ_FLIPPED); + _data[81] = DrawStruct(0, 69, 63, 12, 0); + _data[82] = DrawStruct(0, 75, 63, 12, SPRFLAG_HORIZ_FLIPPED); + _data[83] = DrawStruct(0, 73, 53, 12, 0); + _data[84] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED); + _data[85] = DrawStruct(0, 80, 57, 12, 0); + _data[86] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED); + _data[87] = DrawStruct(7, 65512, 52, 0, SPRFLAG_2000); + _data[88] = DrawStruct(7, 32, 52); + _data[89] = DrawStruct(7, 88, 52); + _data[90] = DrawStruct(0, 144, 52); + _data[91] = DrawStruct(0, 200, 52, 0, SPRFLAG_2000); + _data[92] = DrawStruct(0, 65457, 52, 11, SPRFLAG_2000); + _data[93] = DrawStruct(0, 65509, 52, 11, 0); + _data[94] = DrawStruct(0, 32, 52, 11, 0); + _data[95] = DrawStruct(0, 89, 52, 11, 0); + _data[96] = DrawStruct(0, 145, 52, 11, SPRFLAG_2000); + _data[97] = DrawStruct(0, 65528, 50, 12, 0); + _data[98] = DrawStruct(0, 65471, 50, 12, 0); + _data[99] = DrawStruct(0, 49, 50, 12, 0); + _data[100] = DrawStruct(0, 65471, 50, 12, 0); + _data[101] = DrawStruct(0, 65455, 50, 12, 0); + _data[102] = DrawStruct(0, 49, 50, 12, 0); + _data[103] = DrawStruct(0, 65, 50, 12, 0); + _data[104] = DrawStruct(0, 65512, 50, 12, 0); + _data[105] = DrawStruct(0, 9, 50, 12, 0); + _data[106] = DrawStruct(0, 65528, 50, 12, 0); + _data[107] = DrawStruct(7, 8, 48); + _data[108] = DrawStruct(7, 64, 40); + _data[109] = DrawStruct(6, 144, 40, 0, SPRFLAG_HORIZ_FLIPPED); + _data[110] = DrawStruct(6, 200, 48, 0, SPRFLAG_HORIZ_FLIPPED); + _data[111] = DrawStruct(0, 72, 53, 8, 0); + _data[112] = DrawStruct(0, 72, 53, 8, SPRFLAG_HORIZ_FLIPPED); + _data[113] = DrawStruct(0, 77, 58, 8, 0); + _data[114] = DrawStruct(0, 67, 58, 8, SPRFLAG_HORIZ_FLIPPED); + _data[115] = DrawStruct(0, 81, 47, 8, 0); + _data[116] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED); + _data[117] = DrawStruct(0, 94, 52, 8, 0); + _data[118] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED); + _data[119] = DrawStruct(6, 65496, 40, 0, SPRFLAG_2000); + _data[120] = DrawStruct(6, 64, 40); + _data[121] = DrawStruct(0, 168, 40, 0, SPRFLAG_2000); + _data[122] = DrawStruct(0, 65464, 40, 6, SPRFLAG_2000); + _data[123] = DrawStruct(0, 32, 40, 6, 0); + _data[124] = DrawStruct(0, 137, 40, 6, SPRFLAG_2000); + _data[125] = DrawStruct(0, 65529, 25, 7, 0); + _data[126] = DrawStruct(0, 65424, 25, 7, SPRFLAG_2000); + _data[127] = DrawStruct(0, 98, 25, 7, SPRFLAG_2000); + _data[128] = DrawStruct(0, 65424, 29, 8, SPRFLAG_2000); + _data[129] = DrawStruct(0, 98, 29, 8, SPRFLAG_2000); + _data[130] = DrawStruct(0, 65498, 29, 8, 0); + _data[131] = DrawStruct(0, 25, 29, 8, 0); + _data[132] = DrawStruct(0, 65529, 29, 8, 0); + _data[133] = DrawStruct(6, 32, 24); + _data[134] = DrawStruct(0, 168, 24, 0, SPRFLAG_HORIZ_FLIPPED); + _data[135] = DrawStruct(0, 72, 48, 4, 0); + _data[136] = DrawStruct(0, 72, 48, 4, SPRFLAG_HORIZ_FLIPPED); + _data[137] = DrawStruct(0, 85, 53, 4, 0); + _data[138] = DrawStruct(0, 59, 53, 4, SPRFLAG_HORIZ_FLIPPED); + _data[139] = DrawStruct(0, 89, 41, 4, 0); + _data[140] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED); + _data[141] = DrawStruct(0, 106, 47, 4, 0); + _data[142] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED); + _data[143] = DrawStruct(0, 65400, 24, 0, SPRFLAG_2000); + _data[144] = DrawStruct(0, 8, 12); + _data[145] = DrawStruct(0, 32, 24); + _data[146] = DrawStruct(0, 200, 12, 0, SPRFLAG_HORIZ_FLIPPED); + _data[147] = DrawStruct(0, 200, 24, 0, SPRFLAG_2000); + _data[148] = DrawStruct(0, 32, 24); + _data[149] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[150] = DrawStruct(0, 65469, 10, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[151] = DrawStruct(0, 44, 73); + _data[152] = DrawStruct(0, 44, 73); + _data[153] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[154] = DrawStruct(0, 169, 73); + _data[155] = DrawStruct(0, 169, 73); + _data[156] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[157] = DrawStruct(0, 110, 73); + _data[158] = DrawStruct(0, 110, 73); + _data[159] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[160] = DrawStruct(0, 110, 73); + _data[161] = DrawStruct(0, 110, 73); + _data[162] = DrawStruct(0, 72, 43); + _data[163] = DrawStruct(0, 72, 43, 0, SPRFLAG_HORIZ_FLIPPED); + _data[164] = DrawStruct(0, 93, 48); + _data[165] = DrawStruct(0, 51, 48, 0, SPRFLAG_HORIZ_FLIPPED); + _data[166] = DrawStruct(0, 97, 36); + _data[167] = DrawStruct(0, 47, 36, 0, SPRFLAG_HORIZ_FLIPPED); + _data[168] = DrawStruct(0, 118, 42); + _data[169] = DrawStruct(0, 26, 42, 0, SPRFLAG_HORIZ_FLIPPED); +} + +/*------------------------------------------------------------------------*/ + +InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) { + Common::fill(&_wp[0], &_wp[20], 0); + Common::fill(&_wo[0], &_wo[308], 0); + _overallFrame = 0; + _flipWtr = false; + _flipWall = false; + _flipSky = false; + _flipGround = false; + _isShooting = false; + _charsShooting = false; + _objNumber = 0; +} + +void InterfaceMap::setIndoorsMonsters() { + +} + +void InterfaceMap::setIndoorObjects() { + Common::Point mazePos = _vm->_party._mazePosition; + _objNumber = 0; + const int8 *posOffset = &SCREEN_POSITIONING_X[_vm->_party._mazeDirection][0]; + Common::Point pt; + + Common::Array<MazeObject> &objects = _vm->_map->_mobData._objects; + for (uint idx = 0; idx < objects.size(); ++idx) { + MazeObject &mazeObject = objects[idx]; + + // Determine which half of the X/Y lists to use + int listOffset; + if (_vm->_files->_isDarkCc) { + listOffset = mazeObject._spriteId == 47 ? 1 : 0; + } + else { + listOffset = mazeObject._spriteId == 113 ? 1 : 0; + } + + // Position 1 + pt = Common::Point(mazePos.x + posOffset[2], mazePos.y + posOffset[194]); + if (pt == mazeObject._position && _indoorList._objects0._frame == -1) { + _indoorList._objects0._x = INDOOR_OBJECT_X[listOffset][0]; + _indoorList._objects0._y = INDOOR_OBJECT_Y[listOffset][0]; + _indoorList._objects0._frame = mazeObject._frame; + _indoorList._objects0._sprites = mazeObject._sprites; + _indoorList._objects0._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects0._flags |= SPRFLAG_HORIZ_FLIPPED; + _objNumber = idx; + } + + // Position 2 + pt = Common::Point(mazePos.x + posOffset[7], mazePos.y + posOffset[199]); + if (pt == mazeObject._position && !_wo[27] && _indoorList._objects1._frame == -1) { + _indoorList._objects1._x = INDOOR_OBJECT_X[listOffset][1]; + _indoorList._objects1._y = INDOOR_OBJECT_Y[listOffset][1]; + _indoorList._objects1._frame = mazeObject._frame; + _indoorList._objects1._sprites = mazeObject._sprites; + _indoorList._objects1._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects1._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Position 3 + pt = Common::Point(mazePos.x + posOffset[5], mazePos.y + posOffset[197]); + if (pt == mazeObject._position && (!_wo[27] || !_wo[25]) && (!_wo[27] || !_wo[28]) && + (!_wo[23] || !_wo[25]) && (!_wo[23] || !_wo[28]) && + _indoorList._objects2._frame == -1) { + _indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][2]; + _indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][2]; + _indoorList._objects2._frame = mazeObject._frame; + _indoorList._objects2._sprites = mazeObject._sprites; + _indoorList._objects2._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects2._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Position 4 + pt = Common::Point(mazePos.x + posOffset[9], mazePos.y + posOffset[201]); + if (pt == mazeObject._position && (!_wo[27] || !_wo[26]) && (!_wo[27] || !_wo[29]) && + (!_wo[24] || !_wo[26]) && (!_wo[24] || !_wo[29]) && _indoorList._objects3._frame == -1) { + _indoorList._objects3._x = INDOOR_OBJECT_X[listOffset][3]; + _indoorList._objects3._y = INDOOR_OBJECT_Y[listOffset][3]; + _indoorList._objects3._frame = mazeObject._frame; + _indoorList._objects3._sprites = mazeObject._sprites; + _indoorList._objects3._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects3._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Position 5 + pt = Common::Point(mazePos.x + posOffset[14], mazePos.y + posOffset[206]); + if (pt == mazeObject._position && !_wo[22] && !_wo[27] && _indoorList._objects4._frame == -1) { + _indoorList._objects4._x = INDOOR_OBJECT_X[listOffset][4]; + _indoorList._objects4._y = INDOOR_OBJECT_Y[listOffset][4]; + _indoorList._objects4._frame = mazeObject._frame; + _indoorList._objects4._sprites = mazeObject._sprites; + _indoorList._objects4._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects4._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Position 6 + pt = Common::Point(mazePos.x + posOffset[12], mazePos.y + posOffset[204]); + if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[23]) && (!_wo[22] || !_wo[20]) && + (!_wo[23] || !_wo[17]) && (!_wo[20] || !_wo[17]) && _indoorList._objects5._frame == -1) { + _indoorList._objects5._x = INDOOR_OBJECT_X[listOffset][5]; + _indoorList._objects5._y = INDOOR_OBJECT_Y[listOffset][5]; + _indoorList._objects5._frame = mazeObject._frame; + _indoorList._objects5._sprites = mazeObject._sprites; + _indoorList._objects5._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects5._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Position 7 + pt = Common::Point(mazePos.x + posOffset[16], mazePos.y + posOffset[208]); + if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[24]) && (!_wo[22] || !_wo[21]) && + (!_wo[24] || !_wo[19]) && (!_wo[21] || !_wo[19]) && _indoorList._objects6._frame == -1) { + _indoorList._objects6._x = INDOOR_OBJECT_X[listOffset][6]; + _indoorList._objects6._y = INDOOR_OBJECT_Y[listOffset][6]; + _indoorList._objects6._frame = mazeObject._frame; + _indoorList._objects6._sprites = mazeObject._sprites; + _indoorList._objects6._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects6._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Position 8 + pt = Common::Point(mazePos.x + posOffset[27], mazePos.y + posOffset[219]); + if (pt == mazeObject._position && !_wo[27] && !_wo[22] && !_wo[15] && _indoorList._objects7._frame == -1) { + _indoorList._objects7._x = INDOOR_OBJECT_X[listOffset][7]; + _indoorList._objects7._y = INDOOR_OBJECT_Y[listOffset][7]; + _indoorList._objects7._frame = mazeObject._frame; + _indoorList._objects7._sprites = mazeObject._sprites; + _indoorList._objects7._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects7._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Position 9 + pt = Common::Point(mazePos.x + posOffset[25], mazePos.y + posOffset[217]); + if (pt == mazeObject._position && !_wo[27] && (!_wo[15] || !_wo[17]) && (!_wo[15] || !_wo[12]) && + (!_wo[12] || !_wo[7]) && (!_wo[17] || !_wo[7]) && _indoorList._objects5._frame == -1) { + _indoorList._objects8._x = INDOOR_OBJECT_X[listOffset][8]; + _indoorList._objects8._y = INDOOR_OBJECT_Y[listOffset][8]; + _indoorList._objects8._frame = mazeObject._frame; + _indoorList._objects8._sprites = mazeObject._sprites; + _indoorList._objects8._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects8._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Position 10 + pt = Common::Point(mazePos.x + posOffset[23], mazePos.y + posOffset[215]); + if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[20]) && (!_wo[22] || !_wo[23]) && + (!_wo[20] || !_wo[17]) && (!_wo[23] || !_wo[17]) && !_wo[12] && !_wo[8] && + _indoorList._objects9._frame == -1) { + _indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][9]; + _indoorList._objects9._y = INDOOR_OBJECT_Y[listOffset][9]; + _indoorList._objects9._frame = mazeObject._frame; + _indoorList._objects9._sprites = mazeObject._sprites; + _indoorList._objects9._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects9._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Block 11 + pt = Common::Point(mazePos.x + posOffset[29], mazePos.y + posOffset[221]); + if (pt == mazeObject._position && !_wo[27] && !_wo[22] && (!_wo[15] || !_wo[19]) && + (!_wo[15] || !_wo[14]) && (!_wo[14] || !_wo[9]) && (!_wo[19] || !_wo[9]) && + _indoorList._objects10._frame == -1) { + _indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][10]; + _indoorList._objects10._y = INDOOR_OBJECT_Y[listOffset][10]; + _indoorList._objects10._frame = mazeObject._frame; + _indoorList._objects10._sprites = mazeObject._sprites; + _indoorList._objects10._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects10._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + // Block 12 + pt = Common::Point(mazePos.x + posOffset[31], mazePos.y + posOffset[223]); + if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[21]) && (!_wo[22] || !_wo[24]) && + (!_wo[21] || !_wo[19]) && (!_wo[24] || !_wo[19]) && !_wo[14] && !_wo[10] && + _indoorList._objects11._frame == -1) { + _indoorList._objects11._x = INDOOR_OBJECT_X[listOffset][11]; + _indoorList._objects11._y = INDOOR_OBJECT_Y[listOffset][11]; + _indoorList._objects11._frame = mazeObject._frame; + _indoorList._objects11._sprites = mazeObject._sprites; + _indoorList._objects11._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects11._flags |= SPRFLAG_HORIZ_FLIPPED; + } + } +} + +void InterfaceMap::setIndoorWallPics() { + // TODO +} + +void InterfaceMap::setOutdoorsMonsters() { + +} + +void InterfaceMap::setOutdoorsObjects() { + +} + +void InterfaceMap::drawIndoors() { + Map &map = *_vm->_map; + int surfaceId; + int idx; + + for (int cellIndex = 0; cellIndex < 25; ++cellIndex) { + map.getCell(DRAW_NUMBERS[cellIndex]); + + DrawStruct &drawStruct = _indoorList[3 + cellIndex]; + drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId]; + + surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; + if (surfaceId == 5 || surfaceId == 12) { + drawStruct._flags = _flipWtr; + drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWtr ? 1 : 0]; + } + else { + drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWall ? 1 : 0]; + drawStruct._flags = _flipWall ? 0 : SPRFLAG_HORIZ_FLIPPED; + } + } + + if (!_wo[27] && !_wo[20] && !_wo[23] && !_wo[12] && !_wo[8] && !_wo[30]) { + if (_wo[39]) + _indoorList._swl_4F4L._frame = 22; + else if (_wo[83]) + _indoorList._swl_4F4L._frame = 46; + } + + if (!_wo[27] && !_wo[22] && !_wo[17] && !_wo[12] && !_wo[8]) { + if (_wo[38]) + _indoorList._swl_4F3L._frame = 20; + else if (_wo[82]) + _indoorList._swl_4F3L._frame = 44; + } + + if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[2] && !_wo[7]) { + if (_wo[37]) + _indoorList._swl_4F2L._frame = 18; + else if (_wo[81]) + _indoorList._swl_4F2L._frame = 42; + } + + if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[6]) { + if (_wo[36]) + _indoorList._swl_4F1L._frame = 16; + else if (_wo[80]) + _indoorList._swl_4F1L._frame = 40; + } + + if (!_wo[27] && !_wo[21] && !_wo[24] && !_wo[14] && !_wo[10] && !_wo[31]) { + if (_wo[43]) + _indoorList._swl_4F4R._frame = 23; + else if (_wo[87]) + _indoorList._swl_4F4R._frame = 47; + } + + if (!_wo[27] && !_wo[22] && !_wo[19] && !_wo[14] && !_wo[10]) { + if (_wo[42]) + _indoorList._swl_4F3R._frame = 21; + else if (_wo[86]) + _indoorList._swl_4F3R._frame = 45; + } + + if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[5] && !_wo[9]) { + if (_wo[41]) + _indoorList._swl_4F2R._frame = 19; + else if (_wo[85]) + _indoorList._swl_4F2R._frame = 43; + } + + if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[6]) { + if (_wo[40]) + _indoorList._swl_4F1R._frame = 17; + else if (_wo[84]) + _indoorList._swl_4F1R._frame = 41; + } + + if (!_wo[25] && !_wo[28] && !_wo[20] && !_wo[11] && + !_wo[16] && !_wo[30] && !_wo[32]) { + if (_wo[88]) + _indoorList._fwl_4F4L._frame = 7; + else if (_wo[78]) + _indoorList._fwl_4F4L._frame = 16; + else if (_wo[148]) + _indoorList._fwl_4F4L._frame = _overallFrame + 1; + else if (_wo[108]) + _indoorList._fwl_4F4L._frame = 8; + else if (_wo[168]) + _indoorList._fwl_4F4L._frame = 10; + else if (_wo[128]) + _indoorList._fwl_4F4L._frame = 9; + else if (_wo[34]) + _indoorList._fwl_4F4L._frame = 0; + else if (_wo[188]) + _indoorList._fwl_4F4L._frame = 15; + else if (_wo[208]) + _indoorList._fwl_4F4L._frame = 14; + else if (_wo[228]) + _indoorList._fwl_4F4L._frame = 6; + else if (_wo[248]) + _indoorList._fwl_4F4L._frame = 11; + else if (_wo[268]) + _indoorList._fwl_4F4L._frame = 12; + else if (_wo[288]) + _indoorList._fwl_4F4L._frame = 13; + } + + if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31] && !_wo[33]) { + if (_wo[93]) + _indoorList._fwl_4F4R._frame = 7; + else if (_wo[79]) + _indoorList._fwl_4F4R._frame = 16; + else if (_wo[153]) + _indoorList._fwl_4F4R._frame = _overallFrame + 1; + else if (_wo[113]) + _indoorList._fwl_4F4R._frame = 8; + else if (_wo[173]) + _indoorList._fwl_4F4R._frame = 10; + else if (_wo[133]) + _indoorList._fwl_4F4R._frame = 9; + else if (_wo[35]) + _indoorList._fwl_4F4R._frame = 0; + else if (_wo[79]) + _indoorList._fwl_4F4R._frame = 15; + else if (_wo[213]) + _indoorList._fwl_4F4R._frame = 14; + else if (_wo[233]) + _indoorList._fwl_4F4R._frame = 6; + else if (_wo[253]) + _indoorList._fwl_4F4R._frame = 11; + else if (_wo[273]) + _indoorList._fwl_4F4R._frame = 12; + else if (_wo[293]) + _indoorList._fwl_4F4R._frame = 13; + } + + if (!_wo[25] && !_wo[28] && !_wo[20] && !_wo[11] && !_wo[16] && !_wo[30]) { + if (_wo[32]) + _indoorList._swl_3F4L._frame = 14; + else if (_wo[76]) + _indoorList._swl_3F4L._frame = 38; + } + + if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31]) { + if (_wo[33]) + _indoorList._fwl_3F1R._frame = 15; + else if (_wo[77]) + _indoorList._swl_3F1R._frame = 39; + } + + if (_wo[28] && _wo[27]) { + } + else if (_wo[28] && _wo[12]) { + } + else if (_wo[28] && _wo[23]) { + } + else if (_wo[28] && _wo[8]) { + } + else if (_wo[25] && _wo[27]) { + } + else if (_wo[25] && _wo[12]) { + } + else if (_wo[25] && _wo[23]) { + } + else if (_wo[25] && _wo[8]) { + } + else if (_wo[11] && _wo[27]) { + } + else if (_wo[11] && _wo[12]) { + } + else if (_wo[11] && _wo[23]) { + } + else if (_wo[11] && _wo[8]) { + } + else if (_wo[17] && _wo[27]) { + } + else if (_wo[17] && _wo[12]) { + } + else if (_wo[17] && _wo[23]) { + } + else if (_wo[17] && _wo[8]) { + } + else if (_wo[20]) { + } + else if (_wo[30]) { + _indoorList._swl_3F3L._frame = 12; + } + else if (_wo[74]) { + _indoorList._swl_3F3L._frame = 36; + } + + if (_wo[29] && _wo[27]) { + } + else if (_wo[29] && _wo[14]) { + } + else if (_wo[29] && _wo[24]) { + } + else if (_wo[29] && _wo[10]) { + } + else if (_wo[26] && _wo[27]) { + } + else if (_wo[26] && _wo[14]) { + } + else if (_wo[26] && _wo[24]) { + } + else if (_wo[26] && _wo[10]) { + } + else if (_wo[13] && _wo[27]) { + } + else if (_wo[13] && _wo[14]) { + } + else if (_wo[13] && _wo[24]) { + } + else if (_wo[13] && _wo[10]) { + } + else if (_wo[19] && _wo[27]) { + } + else if (_wo[19] && _wo[24]) { + } + else if (_wo[19] && _wo[10]) { + } + else if (_wo[21]) { + } + else if (_wo[31]) { + _indoorList._swl_3F2R._frame = 13; + } + else if (_wo[75]) { + _indoorList._swl_3F2R._frame = 37; + } + + if (!_wo[27] && !_wo[20] && !_wo[12] && !_wo[23] && !_wo[8] && !_wo[30]) { + if (_wo[89]) + _indoorList._fwl_4F3L._frame = 7; + else if (_wo[44]) + _indoorList._fwl_4F3L._frame = 16; + else if (_wo[149]) + _indoorList._fwl_4F3L._frame = _overallFrame + 1; + else if (_wo[109]) + _indoorList._fwl_4F3L._frame = 8; + else if (_wo[169]) + _indoorList._fwl_4F3L._frame = 10; + else if (_wo[129]) + _indoorList._fwl_4F3L._frame = 9; + else if (_wo[0]) + _indoorList._fwl_4F3L._frame = 0; + else if (_wo[189]) + _indoorList._fwl_4F3L._frame = 15; + else if (_wo[209]) + _indoorList._fwl_4F3L._frame = 14; + else if (_wo[229]) + _indoorList._fwl_4F3L._frame = 6; + else if (_wo[249]) + _indoorList._fwl_4F3L._frame = 11; + else if (_wo[269]) + _indoorList._fwl_4F3L._frame = 12; + else if (_wo[289]) + _indoorList._fwl_4F3L._frame = 13; + } + + if (_wo[22] && _wo[20]) { + } + else if (_wo[22] && _wo[23]) { + } + else if (_wo[20] && _wo[17]) { + } + else if (_wo[23] && _wo[17]) { + } + else if (_wo[12]) { + } + else if (_wo[8]) { + } + else if (_wo[90]) { + _indoorList._fwl_4F2L._frame = 7; + } + else if (_wo[45]) { + _indoorList._fwl_4F2L._frame = 16; + } + else if (_wo[150]) { + _indoorList._fwl_4F2L._frame = _overallFrame + 1; + } + else if (_wo[110]) { + _indoorList._fwl_4F2L._frame = 8; + } + else if (_wo[170]) { + _indoorList._fwl_4F2L._frame = 10; + } + else if (_wo[130]) { + _indoorList._fwl_4F2L._frame = 9; + } + else if (_wo[1]) { + _indoorList._fwl_4F2L._frame = 0; + } + else if (_wo[190]) { + _indoorList._fwl_4F2L._frame = 15; + } + else if (_wo[210]) { + _indoorList._fwl_4F2L._frame = 14; + } + else if (_wo[230]) { + _indoorList._fwl_4F2L._frame = 6; + } + else if (_wo[250]) { + _indoorList._fwl_4F2L._frame = 11; + } + else if (_wo[270]) { + _indoorList._fwl_4F2L._frame = 12; + } + else if (_wo[290]) { + _indoorList._fwl_4F2L._frame = 13; + } + + if (_wo[15] && _wo[17]) { + } + else if (_wo[15] && _wo[12]) { + } + else if (_wo[12] && _wo[7]) { + } + else if (_wo[17] && _wo[7]) { + } + else if (_wo[91]) { + _indoorList._fwl_4F1L._frame = 7; + } + else if (_wo[46]) { + _indoorList._fwl_4F1L._frame = 16; + } + else if (_wo[151]) { + _indoorList._fwl_4F1L._frame = _overallFrame + 1; + } + else if (_wo[111]) { + _indoorList._fwl_4F1L._frame = 8; + } + else if (_wo[171]) { + _indoorList._fwl_4F1L._frame = 10; + } + else if (_wo[131]) { + _indoorList._fwl_4F1L._frame = 9; + } + else if (_wo[2]) { + _indoorList._fwl_4F1L._frame = 0; + } + else if (_wo[191]) { + _indoorList._fwl_4F1L._frame = 15; + } + else if (_wo[211]) { + _indoorList._fwl_4F1L._frame = 14; + } + else if (_wo[231]) { + _indoorList._fwl_4F1L._frame = 6; + } + else if (_wo[251]) { + _indoorList._fwl_4F1L._frame = 11; + } + else if (_wo[271]) { + _indoorList._fwl_4F1L._frame = 12; + } + else if (_wo[291]) { + _indoorList._fwl_4F1L._frame = 13; + } + + if (!_wo[27] && !_wo[21] && !_wo[14] && !_wo[24] && !_wo[10] && !_wo[31]) { + if (_wo[92]) { + _indoorList._fwl_4F3R._frame = 7; + } + else if (_wo[47]) { + _indoorList._fwl_4F3R._frame = 16; + } + else if (_wo[152]) { + _indoorList._fwl_4F3R._frame = _overallFrame + 1; + } + else if (_wo[112]) { + _indoorList._fwl_4F3R._frame = 8; + } + else if (_wo[172]) { + _indoorList._fwl_4F3R._frame = 10; + } + else if (_wo[132]) { + _indoorList._fwl_4F3R._frame = 9; + } + else if (_wo[3]) { + _indoorList._fwl_4F3R._frame = 0; + } + else if (_wo[192]) { + _indoorList._fwl_4F3R._frame = 15; + } + else if (_wo[212]) { + _indoorList._fwl_4F3R._frame = 14; + } + else if (_wo[232]) { + _indoorList._fwl_4F3R._frame = 6; + } + else if (_wo[252]) { + _indoorList._fwl_4F3R._frame = 11; + } + else if (_wo[272]) { + _indoorList._fwl_4F3R._frame = 12; + } + else if (_wo[292]) { + _indoorList._fwl_4F3R._frame = 13; + } + } + + if (_wo[22] && _wo[21]) { + } + else if (_wo[22] && _wo[24]) { + } + else if (_wo[21] && _wo[19]) { + } + else if (_wo[24] && _wo[19]) { + } + else if (_wo[14] || _wo[10]) { + } + else if (_wo[94]) { + _indoorList._fwl_4F2R._frame = 7; + } + else if (_wo[48]) { + _indoorList._fwl_4F2R._frame = 16; + } + else if (_wo[154]) { + _indoorList._fwl_4F2R._frame = _overallFrame + 1; + } + else if (_wo[114]) { + _indoorList._fwl_4F2R._frame = 8; + } + else if (_wo[174]) { + _indoorList._fwl_4F2R._frame = 10; + } + else if (_wo[134]) { + _indoorList._fwl_4F2R._frame = 9; + } + else if (_wo[4]) { + _indoorList._fwl_4F2R._frame = 0; + } + else if (_wo[194]) { + _indoorList._fwl_4F2R._frame = 15; + } + else if (_wo[214]) { + _indoorList._fwl_4F2R._frame = 14; + } + else if (_wo[234]) { + _indoorList._fwl_4F2R._frame = 6; + } + else if (_wo[254]) { + _indoorList._fwl_4F2R._frame = 11; + } + else if (_wo[274]) { + _indoorList._fwl_4F2R._frame = 12; + } + else if (_wo[294]) { + _indoorList._fwl_4F2R._frame = 13; + } + + if (_wo[15] && _wo[19]) { + } + else if (_wo[15] && _wo[14]) { + } + else if (_wo[14] && _wo[9]) { + } + else if (_wo[19] && _wo[9]) { + } + else if (_wo[95]) { + _indoorList._fwl_4F1R._frame = 7; + } + else if (_wo[49]) { + _indoorList._fwl_4F1R._frame = 16; + } + else if (_wo[155]) { + _indoorList._fwl_4F1R._frame = _overallFrame + 1; + } + else if (_wo[115]) { + _indoorList._fwl_4F1R._frame = 8; + } + else if (_wo[175]) { + _indoorList._fwl_4F1R._frame = 10; + } + else if (_wo[135]) { + _indoorList._fwl_4F1R._frame = 9; + } + else if (_wo[5]) { + _indoorList._fwl_4F1R._frame = 0; + } + else if (_wo[195]) { + _indoorList._fwl_4F1R._frame = 15; + } + else if (_wo[215]) { + _indoorList._fwl_4F1R._frame = 14; + } + else if (_wo[235]) { + _indoorList._fwl_4F1R._frame = 6; + } + else if (_wo[255]) { + _indoorList._fwl_4F1R._frame = 11; + } + else if (_wo[275]) { + _indoorList._fwl_4F1R._frame = 12; + } + else if (_wo[295]) { + _indoorList._fwl_4F1R._frame = 13; + } + + if (_wo[27] || _wo[22] || _wo[15] || _wo[96]) { + } + else if (_wo[50]) { + _indoorList._fwl_4F._frame = 16; + } + else if (_wo[156]) { + _indoorList._fwl_4F._frame = _overallFrame + 1; + } + else if (_wo[116]) { + _indoorList._fwl_4F._frame = 8; + } + else if (_wo[176]) { + _indoorList._fwl_4F._frame = 10; + } + else if (_wo[136]) { + _indoorList._fwl_4F._frame = 9; + } + else if (_wo[6]) { + _indoorList._fwl_4F._frame = 0; + } + else if (_wo[196]) { + _indoorList._fwl_4F._frame = 15; + } + else if (_wo[216]) { + _indoorList._fwl_4F._frame = 14; + } + else if (_wo[236]) { + _indoorList._fwl_4F._frame = 6; + } + else if (_wo[256]) { + _indoorList._fwl_4F._frame = 11; + } + else if (_wo[276]) { + _indoorList._fwl_4F._frame = 12; + } + else if (_wo[296]) { + _indoorList._fwl_4F._frame = 13; + } + + if (!_wo[27] && !_wo[22] && !_wo[15]) { + if (_wo[7]) + _indoorList._swl_3F1L._frame = 8; + else if (_wo[51]) + _indoorList._swl_3F1L._frame = 32; + } + + if (_wo[22] && _wo[23]) { + } + else if (_wo[22] && _wo[20]) { + } + else if (_wo[17] && _wo[23]) { + } + else if (_wo[17] && _wo[20]) { + } + else if (_wo[8]) { + _indoorList._swl_3F2L._frame = 10; + } + else if (_wo[52]) { + _indoorList._swl_3F2L._frame = 34; + } + + if (_wo[27] || _wo[22] || _wo[15]) { + } + else if (_wo[9]) { + _indoorList._swl_3F4R._frame = 9; + } + else if (_wo[53]) { + _indoorList._swl_3F4R._frame = 33; + } + + if (_wo[22] && _wo[24]) { + } + else if (_wo[22] && _wo[21]) { + } + else if (_wo[19] && _wo[24]) { + } + else if (_wo[19] && _wo[21]) { + } + else if (_wo[14]) { + } + else if (_wo[10]) { + _indoorList._swl_3F3R._frame = 11; + } + else if (_wo[54]) { + _indoorList._swl_3F3R._frame = 35; + } + + if (_wo[25] || _wo[28] || _wo[20] || _wo[16]) { + } + else if (_wo[97]) { + _indoorList._fwl_3F2L._frame = 24; + } + else if (_wo[55]) { + _indoorList._fwl_3F2L._frame = 33; + } + else if (_wo[137]) { + _indoorList._fwl_3F2L._frame = 26; + } + else if (_wo[157]) { + _indoorList._fwl_3F2L._frame = _overallFrame + 18; + } + else if (_wo[117]) { + _indoorList._fwl_3F2L._frame = 25; + } + else if (_wo[177]) { + _indoorList._fwl_3F2L._frame = 27; + } + else if (_wo[11]) { + _indoorList._fwl_3F2L._frame = 17; + } + else if (_wo[197]) { + _indoorList._fwl_3F2L._frame = 32; + } + else if (_wo[217]) { + _indoorList._fwl_3F2L._frame = 31; + } + else if (_wo[237]) { + _indoorList._fwl_3F2L._frame = 23; + } + else if (_wo[257]) { + _indoorList._fwl_3F2L._frame = 28; + } + else if (_wo[277]) { + _indoorList._fwl_3F2L._frame = 29; + } + else if (_wo[297]) { + _indoorList._fwl_3F2L._frame = 30; + } + + if (_wo[22] && _wo[23]) { + } + else if (_wo[22] && _wo[20]) { + } + else if (_wo[23] && _wo[17]) { + } + else if (_wo[20] && _wo[17]) { + } + else if (_wo[98]) { + _indoorList._fwl_3F1L._frame = 24; + } + else if (_wo[56]) { + _indoorList._fwl_3F1L._frame = 33; + } + else if (_wo[178]) { + _indoorList._fwl_3F1L._frame = 27; + } + else if (_wo[118]) { + _indoorList._fwl_3F1L._frame = 25; + } + else if (_wo[158]) { + _indoorList._fwl_3F1L._frame = _overallFrame + 18; + } + else if (_wo[138]) { + _indoorList._fwl_3F1L._frame = 26; + } + else if (_wo[12]) { + _indoorList._fwl_3F1L._frame = 17; + } + else if (_wo[198]) { + _indoorList._fwl_3F1L._frame = 32; + } + else if (_wo[218]) { + _indoorList._fwl_3F1L._frame = 31; + } + else if (_wo[238]) { + _indoorList._fwl_3F1L._frame = 23; + } + else if (_wo[258]) { + _indoorList._fwl_3F1L._frame = 28; + } + else if (_wo[278]) { + _indoorList._fwl_3F1L._frame = 29; + } + else if (_wo[298]) { + _indoorList._fwl_3F1L._frame = 30; + } + + if (_wo[26] || _wo[29] || _wo[21] || _wo[18]) { + } + else if (_wo[99]) { + _indoorList._fwl_3F2R._frame = 24; + } + else if (_wo[57]) { + _indoorList._fwl_3F2R._frame = 33; + } + else if (_wo[139]) { + _indoorList._fwl_3F2R._frame = 26; + } + else if (_wo[159]) { + _indoorList._fwl_3F2R._frame = _overallFrame + 18; + } + else if (_wo[119]) { + _indoorList._fwl_3F2R._frame = 25; + } + else if (_wo[179]) { + _indoorList._fwl_3F2R._frame = 27; + } + else if (_wo[13]) { + _indoorList._fwl_3F2R._frame = 17; + } + else if (_wo[199]) { + _indoorList._fwl_3F2R._frame = 32; + } + else if (_wo[219]) { + _indoorList._fwl_3F2R._frame = 31; + } + else if (_wo[239]) { + _indoorList._fwl_3F2R._frame = 23; + } + else if (_wo[259]) { + _indoorList._fwl_3F2R._frame = 28; + } + else if (_wo[279]) { + _indoorList._fwl_3F2R._frame = 29; + } + else if (_wo[299]) { + _indoorList._fwl_3F2R._frame = 30; + } + + if (_wo[22] && _wo[24]) { + } + else if (_wo[22] && _wo[21]) { + } + else if (_wo[24] && _wo[19]) { + } + else if (_wo[21] && _wo[19]) { + } + else if (_wo[100]) { + _indoorList._fwl_3F1R._frame = 24; + } + else if (_wo[58]) { + _indoorList._fwl_3F1R._frame = 33; + } + else if (_wo[140]) { + _indoorList._fwl_3F1R._frame = 26; + } + else if (_wo[160]) { + _indoorList._fwl_3F1R._frame = _overallFrame + 18; + } + else if (_wo[120]) { + _indoorList._fwl_3F1R._frame = 25; + } + else if (_wo[180]) { + _indoorList._fwl_3F1R._frame = 27; + } + else if (_wo[14]) { + _indoorList._fwl_3F1R._frame = 17; + } + else if (_wo[200]) { + _indoorList._fwl_3F1R._frame = 32; + } + else if (_wo[220]) { + _indoorList._fwl_3F1R._frame = 31; + } + else if (_wo[240]) { + _indoorList._fwl_3F1R._frame = 23; + } + else if (_wo[260]) { + _indoorList._fwl_3F1R._frame = 28; + } + else if (_wo[280]) { + _indoorList._fwl_3F1R._frame = 29; + } + else if (_wo[300]) { + _indoorList._fwl_3F1R._frame = 30; + } + + if (_wo[22] || _wo[27]) { + } + else if (_wo[101]) { + _indoorList._fwl_3F._frame = 24; + } + else if (_wo[59]) { + _indoorList._fwl_3F._frame = 33; + } + else if (_wo[141]) { + _indoorList._fwl_3F._frame = 26; + } + else if (_wo[161]) { + _indoorList._fwl_3F._frame = _overallFrame + 18; + } + else if (_wo[121]) { + _indoorList._fwl_3F._frame = 25; + } + else if (_wo[181]) { + _indoorList._fwl_3F._frame = 27; + } + else if (_wo[15]) { + _indoorList._fwl_3F._frame = 17; + } + else if (_wo[201]) { + _indoorList._fwl_3F._frame = 32; + } + else if (_wo[221]) { + _indoorList._fwl_3F._frame = 31; + } + else if (_wo[241]) { + _indoorList._fwl_3F._frame = 23; + } + else if (_wo[261]) { + _indoorList._fwl_3F._frame = 28; + } + else if (_wo[281]) { + _indoorList._fwl_3F._frame = 29; + } + else if (_wo[301]) { + _indoorList._fwl_3F._frame = 30; + } + + if (_wo[25] || _wo[28] || _wo[20]) { + } + else if (_wo[16]) { + _indoorList._swl_2F2L._frame = 6; + } + else if (_wo[60]) { + _indoorList._swl_2F2L._frame = 30; + } + + if (_wo[27] || _wo[22]) { + } + else if (_wo[17]) { + _indoorList._swl_2F1L._frame = 4; + } + else if (_wo[61]) { + _indoorList._swl_2F1L._frame = 28; + } + + if (_wo[26] || _wo[29] || _wo[21]) { + } + else if (_wo[18]) { + _indoorList._swl_2F2R._frame = 7; + } + else if (_wo[62]) { + _indoorList._swl_2F2R._frame = 31; + } + + if (_wo[27] || _wo[22]) { + } + else if (_wo[19]) { + _indoorList._swl_2F1R._frame = 5; + } + else if (_wo[63]) { + _indoorList._swl_2F1R._frame = 29; + } + + if (_wo[27] && _wo[25]) { + } + else if (_wo[27] && _wo[28]) { + } + else if (_wo[23] & _wo[25]) { + } + else if (_wo[23] && _wo[28]) { + } + else if (_wo[102]) { + _indoorList._fwl_2F1L._frame = 7; + } + else if (_wo[64]) { + _indoorList._fwl_2F1L._frame = 16; + } + else if (_wo[182]) { + _indoorList._fwl_2F1L._frame = 10; + } + else if (_wo[122]) { + _indoorList._fwl_2F1L._frame = 8; + } + else if (_wo[142]) { + _indoorList._fwl_2F1L._frame = 9; + } + else if (_wo[162]) { + _indoorList._fwl_2F1L._frame = _overallFrame + 1; + } + else if (_wo[20]) { + _indoorList._fwl_2F1L._frame = 0; + } + else if (_wo[202]) { + _indoorList._fwl_2F1L._frame = 15; + } + else if (_wo[222]) { + _indoorList._fwl_2F1L._frame = 14; + } + else if (_wo[242]) { + _indoorList._fwl_2F1L._frame = 6; + } + else if (_wo[262]) { + _indoorList._fwl_2F1L._frame = 11; + } + else if (_wo[282]) { + _indoorList._fwl_2F1L._frame = 12; + } + else if (_wo[302]) { + _indoorList._fwl_2F1L._frame = 13; + } + + if (_wo[27] && _wo[26]) { + } + else if (_wo[27] && _wo[29]) { + } + else if (_wo[24] && _wo[26]) { + } + else if (_wo[24] && _wo[29]) { + } + else if (_wo[103]) { + _indoorList._fwl_2F1R._frame = 7; + } + else if (_wo[65]) { + _indoorList._fwl_2F1R._frame = 16; + } + else if (_wo[183]) { + _indoorList._fwl_2F1R._frame = 10; + } + else if (_wo[123]) { + _indoorList._fwl_2F1R._frame = 8; + } + else if (_wo[143]) { + _indoorList._fwl_2F1R._frame = 9; + } + else if (_wo[163]) { + _indoorList._fwl_2F1R._frame = _overallFrame + 1; + } + else if (_wo[21]) { + _indoorList._fwl_2F1R._frame = 0; + } + else if (_wo[203]) { + _indoorList._fwl_2F1R._frame = 15; + } + else if (_wo[223]) { + _indoorList._fwl_2F1R._frame = 14; + } + else if (_wo[243]) { + _indoorList._fwl_2F1R._frame = 6; + } + else if (_wo[263]) { + _indoorList._fwl_2F1R._frame = 11; + } + else if (_wo[283]) { + _indoorList._fwl_2F1R._frame = 12; + } + else if (_wo[303]) { + _indoorList._fwl_2F1R._frame = 13; + } + + if (_wo[27]) { + + } + else if (_wo[104]) { + _indoorList._fwl_2F._frame = 7; + } + else if (_wo[66]) { + _indoorList._fwl_2F._frame = 16; + } + else if (_wo[184]) { + _indoorList._fwl_2F._frame = 10; + } + else if (_wo[124]) { + _indoorList._fwl_2F._frame = 8; + } + else if (_wo[144]) { + _indoorList._fwl_2F._frame = 9; + } + else if (_wo[164]) { + _indoorList._fwl_2F._frame = _overallFrame + 1; + } + else if (_wo[22]) { + _indoorList._fwl_2F._frame = 0; + } + else if (_wo[204]) { + _indoorList._fwl_2F._frame = 15; + } + else if (_wo[224]) { + _indoorList._fwl_2F._frame = 14; + } + else if (_wo[244]) { + _indoorList._fwl_2F._frame = 6; + } + else if (_wo[264]) { + _indoorList._fwl_2F._frame = 11; + } + else if (_wo[284]) { + _indoorList._fwl_2F._frame = 12; + } + else if (_wo[304]) { + _indoorList._fwl_2F._frame = 13; + } + + if (_wo[27]) { + } + else if (_wo[23]) { + _indoorList._swl_1F1L._frame = 2; + } + else if (_wo[67]) { + _indoorList._swl_1F1L._frame = 26; + } + + if (_wo[27]) { + } + else if (_wo[24]) { + _indoorList._swl_1F1R._frame = 3; + } + else if (_wo[68]) { + _indoorList._swl_1F1R._frame = 27; + } + + if (_wo[28]) { + } + else if (_wo[105] || _wo[25] || _wo[165] || _wo[125] || _wo[185] || _wo[145]) { + _indoorList._fwl_1F1L._frame = 0; + _indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl1; + } + else if (_wo[69]) { + _indoorList._fwl_1F1L._frame = 9; + _indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl2; + } + + if (_wo[29]) { + } + else if (_wo[106] || _wo[26] || _wo[166] || _wo[126] || _wo[186] || _wo[146]) { + _indoorList._fwl_1F._frame = 0; + _indoorList._fwl_1F._sprites = &map._wallSprites._fwl1; + } + else if (_wo[70]) { + _indoorList._fwl_1F._frame = 9; + _indoorList._fwl_1F._sprites = &map._wallSprites._fwl2; + } + + if (_wo[107]) { + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + if (_vm->_openDoor) + _indoorList._fwl_1F1R._frame = 0; + else + _indoorList._fwl_1F1R._frame = map.mazeData()._wallKind ? 1 : 10; + } + else if (_wo[71]) { + _indoorList._fwl_1F1R._frame = 9; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[167]) { + _indoorList._fwl_1F1R._frame = _overallFrame + 1; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[127]) { + _indoorList._fwl_1F1R._frame = 1; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[147]) { + _indoorList._fwl_1F1R._frame = 2; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[187]) { + _indoorList._fwl_1F1R._frame = 3; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[27]) { + _indoorList._fwl_1F1R._frame = 0; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1; + } + else if (_wo[207]) { + _indoorList._fwl_1F1R._frame = 8; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[227]) { + _indoorList._fwl_1F1R._frame = 7; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[247]) { + _indoorList._fwl_1F1R._frame = 6; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1; + } + else if (_wo[267]) { + _indoorList._fwl_1F1R._frame = 4; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[287]) { + _indoorList._fwl_1F1R._frame = 5; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + else if (_wo[307]) { + _indoorList._fwl_1F1R._frame = 6; + _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; + } + + if (_wo[28]) { + _indoorList._swl_0F1L._frame = 0; + } + else if (_wo[72]) { + _indoorList._swl_0F1L._frame = 24; + } + + if (_wo[29]) { + _indoorList._swl_0F1R._frame = 1; + } + else if (_wo[73]) { + _indoorList._swl_0F1R._frame = 25; + } + + map.cellFlagLookup(_vm->_party._mazePosition); + + // WORKAROUND: Original did an array lookup on _skySprites. + // Was this a feature for multiple skys that was abandoned? + _indoorList[0]._sprites = &map._skySprites; + _indoorList[0]._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0; + + if (_vm->_openDoor) { + Common::Point pt( + _vm->_party._mazePosition.x + SCREEN_POSITIONING_X[ + _vm->_party._mazeDirection][_vm->_party._mazePosition.x], + _vm->_party._mazePosition.y + SCREEN_POSITIONING_Y[ + _vm->_party._mazeDirection][_vm->_party._mazePosition.y] + ); + map.cellFlagLookup(pt); + + _indoorList._sky._sprites = &map._skySprites; + } else { + _indoorList._sky._sprites = _indoorList[0]._sprites; + } + + _indoorList._sky._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0; + _indoorList._ground._flags = _flipGround ? SPRFLAG_HORIZ_FLIPPED : 0; + _indoorList._horizon._frame = 7; + + // Finally draw the darn indoor scene + _vm->_screen->_windows[3].drawList(&_indoorList[0], _indoorList.size()); + + // Check for any character shooting + _isShooting = false; + for (int i = 0; i < _vm->_party._partyCount; ++i) { + if (_vm->_combat->_shooting[i]) + _isShooting = true; + } + + _charsShooting = _isShooting; + + // TODO +} + +} // End of namespace Xeen diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h new file mode 100644 index 0000000000..01cd1d2c48 --- /dev/null +++ b/engines/xeen/interface_map.h @@ -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. + * + */ + +#ifndef XEEN_INTERFACE_MAP_H +#define XEEN_INTERFACE_MAP_H + +#include "common/scummsys.h" +#include "xeen/screen.h" + +namespace Xeen { + +class XeenEngine; + +class OutdoorDrawList { +public: + DrawStruct _data[132]; + DrawStruct &_skySprite; + DrawStruct &_groundSprite; +public: + OutdoorDrawList(); + + DrawStruct &operator[](int idx) { + assert(idx < size()); + return _data[idx]; + } + + int size() const { return 132; } +}; + +class IndoorDrawList { +public: + DrawStruct _data[170]; + DrawStruct &_sky; + DrawStruct &_ground; + DrawStruct &_horizon; + DrawStruct &_swl_0F1R, _swl_0F1L, _swl_1F1R, _swl_1F1L, + _swl_2F2R, _swl_2F1R, _swl_2F1L, _swl_2F2L, + _swl_3F1R, _swl_3F2R, _swl_3F3R, _swl_3F4R, + _swl_3F1L, _swl_3F2L, _swl_3F3L, _swl_3F4L, + _swl_4F4R, _swl_4F3R, _swl_4F2R, _swl_4F1R, + _swl_4F1L, _swl_4F2L, _swl_4F3L, _swl_4F4L; + DrawStruct &_fwl_4F4R, _fwl_4F3R, _fwl_4F2R, _fwl_4F1R, + _fwl_4F, _fwl_4F1L, _fwl_4F2L, _fwl_4F3L, _fwl_4F4L; + DrawStruct &_fwl_2F1R, _fwl_2F, _fwl_2F1L, _fwl_3F2R, + _fwl_3F1R, _fwl_3F, _fwl_3F1L, _fwl_3F2L; + DrawStruct &_fwl_1F, _fwl_1F1R, _fwl_1F1L; + DrawStruct &_objects0, _objects1, _objects2, _objects3; + DrawStruct &_objects4, _objects5, _objects6, _objects7; + DrawStruct &_objects8, _objects9, _objects10, _objects11; +public: + IndoorDrawList(); + + DrawStruct &operator[](int idx) { + assert(idx < size()); + return _data[idx]; + } + + int size() const { return 170; } +}; + + +class InterfaceMap { +private: + XeenEngine *_vm; + + void initDrawStructs(); +protected: + byte _wp[20]; + byte _wo[308]; + int _overallFrame; + bool _flipWtr; + bool _flipWall; + bool _flipSky; + bool _flipGround; + bool _isShooting; + bool _charsShooting; + int _objNumber; +public: + OutdoorDrawList _outdoorList; + IndoorDrawList _indoorList; +public: + InterfaceMap(XeenEngine *vm); + + void setIndoorsMonsters(); + + void setIndoorObjects(); + + void setIndoorWallPics(); + + void drawIndoors(); + + void setOutdoorsMonsters(); + + void setOutdoorsObjects(); +}; + +} // End of namespace Xeen + +#endif /* XEEN_INTERFACE_MAP_H */ diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 2c22322f25..d6b8097386 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -14,6 +14,7 @@ MODULE_OBJS := \ files.o \ font.o \ interface.o \ + interface_map.o \ items.o \ map.o \ party.o \ -- cgit v1.2.3 From 17f946305cfeeaa03b070510798c79437fe055ef Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 14 Jan 2015 20:48:40 -0500 Subject: XEEN: Formatting fixes --- engines/xeen/interface_map.cpp | 859 ++++++++++++++--------------------------- 1 file changed, 286 insertions(+), 573 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index d88f9421ed..af52178ba1 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -582,8 +582,7 @@ void InterfaceMap::drawIndoors() { if (surfaceId == 5 || surfaceId == 12) { drawStruct._flags = _flipWtr; drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWtr ? 1 : 0]; - } - else { + } else { drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWall ? 1 : 0]; drawStruct._flags = _flipWall ? 0 : SPRFLAG_HORIZ_FLIPPED; } @@ -719,82 +718,47 @@ void InterfaceMap::drawIndoors() { } if (_wo[28] && _wo[27]) { - } - else if (_wo[28] && _wo[12]) { - } - else if (_wo[28] && _wo[23]) { - } - else if (_wo[28] && _wo[8]) { - } - else if (_wo[25] && _wo[27]) { - } - else if (_wo[25] && _wo[12]) { - } - else if (_wo[25] && _wo[23]) { - } - else if (_wo[25] && _wo[8]) { - } - else if (_wo[11] && _wo[27]) { - } - else if (_wo[11] && _wo[12]) { - } - else if (_wo[11] && _wo[23]) { - } - else if (_wo[11] && _wo[8]) { - } - else if (_wo[17] && _wo[27]) { - } - else if (_wo[17] && _wo[12]) { - } - else if (_wo[17] && _wo[23]) { - } - else if (_wo[17] && _wo[8]) { - } - else if (_wo[20]) { - } - else if (_wo[30]) { + } else if (_wo[28] && _wo[12]) { + } else if (_wo[28] && _wo[23]) { + } else if (_wo[28] && _wo[8]) { + } else if (_wo[25] && _wo[27]) { + } else if (_wo[25] && _wo[12]) { + } else if (_wo[25] && _wo[23]) { + } else if (_wo[25] && _wo[8]) { + } else if (_wo[11] && _wo[27]) { + } else if (_wo[11] && _wo[12]) { + } else if (_wo[11] && _wo[23]) { + } else if (_wo[11] && _wo[8]) { + } else if (_wo[17] && _wo[27]) { + } else if (_wo[17] && _wo[12]) { + } else if (_wo[17] && _wo[23]) { + } else if (_wo[17] && _wo[8]) { + } else if (_wo[20]) { + } else if (_wo[30]) { _indoorList._swl_3F3L._frame = 12; - } - else if (_wo[74]) { + } else if (_wo[74]) { _indoorList._swl_3F3L._frame = 36; } if (_wo[29] && _wo[27]) { - } - else if (_wo[29] && _wo[14]) { - } - else if (_wo[29] && _wo[24]) { - } - else if (_wo[29] && _wo[10]) { - } - else if (_wo[26] && _wo[27]) { - } - else if (_wo[26] && _wo[14]) { - } - else if (_wo[26] && _wo[24]) { - } - else if (_wo[26] && _wo[10]) { - } - else if (_wo[13] && _wo[27]) { - } - else if (_wo[13] && _wo[14]) { - } - else if (_wo[13] && _wo[24]) { - } - else if (_wo[13] && _wo[10]) { - } - else if (_wo[19] && _wo[27]) { - } - else if (_wo[19] && _wo[24]) { - } - else if (_wo[19] && _wo[10]) { - } - else if (_wo[21]) { - } - else if (_wo[31]) { + } else if (_wo[29] && _wo[14]) { + } else if (_wo[29] && _wo[24]) { + } else if (_wo[29] && _wo[10]) { + } else if (_wo[26] && _wo[27]) { + } else if (_wo[26] && _wo[14]) { + } else if (_wo[26] && _wo[24]) { + } else if (_wo[26] && _wo[10]) { + } else if (_wo[13] && _wo[27]) { + } else if (_wo[13] && _wo[14]) { + } else if (_wo[13] && _wo[24]) { + } else if (_wo[13] && _wo[10]) { + } else if (_wo[19] && _wo[27]) { + } else if (_wo[19] && _wo[24]) { + } else if (_wo[19] && _wo[10]) { + } else if (_wo[21]) { + } else if (_wo[31]) { _indoorList._swl_3F2R._frame = 13; - } - else if (_wo[75]) { + } else if (_wo[75]) { _indoorList._swl_3F2R._frame = 37; } @@ -828,281 +792,190 @@ void InterfaceMap::drawIndoors() { } if (_wo[22] && _wo[20]) { - } - else if (_wo[22] && _wo[23]) { - } - else if (_wo[20] && _wo[17]) { - } - else if (_wo[23] && _wo[17]) { - } - else if (_wo[12]) { - } - else if (_wo[8]) { - } - else if (_wo[90]) { + } else if (_wo[22] && _wo[23]) { + } else if (_wo[20] && _wo[17]) { + } else if (_wo[23] && _wo[17]) { + } else if (_wo[12]) { + } else if (_wo[8]) { + } else if (_wo[90]) { _indoorList._fwl_4F2L._frame = 7; - } - else if (_wo[45]) { + } else if (_wo[45]) { _indoorList._fwl_4F2L._frame = 16; - } - else if (_wo[150]) { + } else if (_wo[150]) { _indoorList._fwl_4F2L._frame = _overallFrame + 1; - } - else if (_wo[110]) { + } else if (_wo[110]) { _indoorList._fwl_4F2L._frame = 8; - } - else if (_wo[170]) { + } else if (_wo[170]) { _indoorList._fwl_4F2L._frame = 10; - } - else if (_wo[130]) { + } else if (_wo[130]) { _indoorList._fwl_4F2L._frame = 9; - } - else if (_wo[1]) { + } else if (_wo[1]) { _indoorList._fwl_4F2L._frame = 0; - } - else if (_wo[190]) { + } else if (_wo[190]) { _indoorList._fwl_4F2L._frame = 15; - } - else if (_wo[210]) { + } else if (_wo[210]) { _indoorList._fwl_4F2L._frame = 14; - } - else if (_wo[230]) { + } else if (_wo[230]) { _indoorList._fwl_4F2L._frame = 6; - } - else if (_wo[250]) { + } else if (_wo[250]) { _indoorList._fwl_4F2L._frame = 11; - } - else if (_wo[270]) { + } else if (_wo[270]) { _indoorList._fwl_4F2L._frame = 12; - } - else if (_wo[290]) { + } else if (_wo[290]) { _indoorList._fwl_4F2L._frame = 13; } if (_wo[15] && _wo[17]) { - } - else if (_wo[15] && _wo[12]) { - } - else if (_wo[12] && _wo[7]) { - } - else if (_wo[17] && _wo[7]) { - } - else if (_wo[91]) { + } else if (_wo[15] && _wo[12]) { + } else if (_wo[12] && _wo[7]) { + } else if (_wo[17] && _wo[7]) { + } else if (_wo[91]) { _indoorList._fwl_4F1L._frame = 7; - } - else if (_wo[46]) { + } else if (_wo[46]) { _indoorList._fwl_4F1L._frame = 16; - } - else if (_wo[151]) { + } else if (_wo[151]) { _indoorList._fwl_4F1L._frame = _overallFrame + 1; - } - else if (_wo[111]) { + } else if (_wo[111]) { _indoorList._fwl_4F1L._frame = 8; - } - else if (_wo[171]) { + } else if (_wo[171]) { _indoorList._fwl_4F1L._frame = 10; - } - else if (_wo[131]) { + } else if (_wo[131]) { _indoorList._fwl_4F1L._frame = 9; - } - else if (_wo[2]) { + } else if (_wo[2]) { _indoorList._fwl_4F1L._frame = 0; - } - else if (_wo[191]) { + } else if (_wo[191]) { _indoorList._fwl_4F1L._frame = 15; - } - else if (_wo[211]) { + } else if (_wo[211]) { _indoorList._fwl_4F1L._frame = 14; - } - else if (_wo[231]) { + } else if (_wo[231]) { _indoorList._fwl_4F1L._frame = 6; - } - else if (_wo[251]) { + } else if (_wo[251]) { _indoorList._fwl_4F1L._frame = 11; - } - else if (_wo[271]) { + } else if (_wo[271]) { _indoorList._fwl_4F1L._frame = 12; - } - else if (_wo[291]) { + } else if (_wo[291]) { _indoorList._fwl_4F1L._frame = 13; } if (!_wo[27] && !_wo[21] && !_wo[14] && !_wo[24] && !_wo[10] && !_wo[31]) { if (_wo[92]) { _indoorList._fwl_4F3R._frame = 7; - } - else if (_wo[47]) { + } else if (_wo[47]) { _indoorList._fwl_4F3R._frame = 16; - } - else if (_wo[152]) { + } else if (_wo[152]) { _indoorList._fwl_4F3R._frame = _overallFrame + 1; - } - else if (_wo[112]) { + } else if (_wo[112]) { _indoorList._fwl_4F3R._frame = 8; - } - else if (_wo[172]) { + } else if (_wo[172]) { _indoorList._fwl_4F3R._frame = 10; - } - else if (_wo[132]) { + } else if (_wo[132]) { _indoorList._fwl_4F3R._frame = 9; - } - else if (_wo[3]) { + } else if (_wo[3]) { _indoorList._fwl_4F3R._frame = 0; - } - else if (_wo[192]) { + } else if (_wo[192]) { _indoorList._fwl_4F3R._frame = 15; - } - else if (_wo[212]) { + } else if (_wo[212]) { _indoorList._fwl_4F3R._frame = 14; - } - else if (_wo[232]) { + } else if (_wo[232]) { _indoorList._fwl_4F3R._frame = 6; - } - else if (_wo[252]) { + } else if (_wo[252]) { _indoorList._fwl_4F3R._frame = 11; - } - else if (_wo[272]) { + } else if (_wo[272]) { _indoorList._fwl_4F3R._frame = 12; - } - else if (_wo[292]) { + } else if (_wo[292]) { _indoorList._fwl_4F3R._frame = 13; } } if (_wo[22] && _wo[21]) { - } - else if (_wo[22] && _wo[24]) { - } - else if (_wo[21] && _wo[19]) { - } - else if (_wo[24] && _wo[19]) { - } - else if (_wo[14] || _wo[10]) { - } - else if (_wo[94]) { + } else if (_wo[22] && _wo[24]) { + } else if (_wo[21] && _wo[19]) { + } else if (_wo[24] && _wo[19]) { + } else if (_wo[14] || _wo[10]) { + } else if (_wo[94]) { _indoorList._fwl_4F2R._frame = 7; - } - else if (_wo[48]) { + } else if (_wo[48]) { _indoorList._fwl_4F2R._frame = 16; - } - else if (_wo[154]) { + } else if (_wo[154]) { _indoorList._fwl_4F2R._frame = _overallFrame + 1; - } - else if (_wo[114]) { + } else if (_wo[114]) { _indoorList._fwl_4F2R._frame = 8; - } - else if (_wo[174]) { + } else if (_wo[174]) { _indoorList._fwl_4F2R._frame = 10; - } - else if (_wo[134]) { + } else if (_wo[134]) { _indoorList._fwl_4F2R._frame = 9; - } - else if (_wo[4]) { + } else if (_wo[4]) { _indoorList._fwl_4F2R._frame = 0; - } - else if (_wo[194]) { + } else if (_wo[194]) { _indoorList._fwl_4F2R._frame = 15; - } - else if (_wo[214]) { + } else if (_wo[214]) { _indoorList._fwl_4F2R._frame = 14; - } - else if (_wo[234]) { + } else if (_wo[234]) { _indoorList._fwl_4F2R._frame = 6; - } - else if (_wo[254]) { + } else if (_wo[254]) { _indoorList._fwl_4F2R._frame = 11; - } - else if (_wo[274]) { + } else if (_wo[274]) { _indoorList._fwl_4F2R._frame = 12; - } - else if (_wo[294]) { + } else if (_wo[294]) { _indoorList._fwl_4F2R._frame = 13; } if (_wo[15] && _wo[19]) { - } - else if (_wo[15] && _wo[14]) { - } - else if (_wo[14] && _wo[9]) { - } - else if (_wo[19] && _wo[9]) { - } - else if (_wo[95]) { + } else if (_wo[15] && _wo[14]) { + } else if (_wo[14] && _wo[9]) { + } else if (_wo[19] && _wo[9]) { + } else if (_wo[95]) { _indoorList._fwl_4F1R._frame = 7; - } - else if (_wo[49]) { + } else if (_wo[49]) { _indoorList._fwl_4F1R._frame = 16; - } - else if (_wo[155]) { + } else if (_wo[155]) { _indoorList._fwl_4F1R._frame = _overallFrame + 1; - } - else if (_wo[115]) { + } else if (_wo[115]) { _indoorList._fwl_4F1R._frame = 8; - } - else if (_wo[175]) { + } else if (_wo[175]) { _indoorList._fwl_4F1R._frame = 10; - } - else if (_wo[135]) { + } else if (_wo[135]) { _indoorList._fwl_4F1R._frame = 9; - } - else if (_wo[5]) { + } else if (_wo[5]) { _indoorList._fwl_4F1R._frame = 0; - } - else if (_wo[195]) { + } else if (_wo[195]) { _indoorList._fwl_4F1R._frame = 15; - } - else if (_wo[215]) { + } else if (_wo[215]) { _indoorList._fwl_4F1R._frame = 14; - } - else if (_wo[235]) { + } else if (_wo[235]) { _indoorList._fwl_4F1R._frame = 6; - } - else if (_wo[255]) { + } else if (_wo[255]) { _indoorList._fwl_4F1R._frame = 11; - } - else if (_wo[275]) { + } else if (_wo[275]) { _indoorList._fwl_4F1R._frame = 12; - } - else if (_wo[295]) { + } else if (_wo[295]) { _indoorList._fwl_4F1R._frame = 13; } if (_wo[27] || _wo[22] || _wo[15] || _wo[96]) { - } - else if (_wo[50]) { + } else if (_wo[50]) { _indoorList._fwl_4F._frame = 16; - } - else if (_wo[156]) { + } else if (_wo[156]) { _indoorList._fwl_4F._frame = _overallFrame + 1; - } - else if (_wo[116]) { + } else if (_wo[116]) { _indoorList._fwl_4F._frame = 8; - } - else if (_wo[176]) { + } else if (_wo[176]) { _indoorList._fwl_4F._frame = 10; - } - else if (_wo[136]) { + } else if (_wo[136]) { _indoorList._fwl_4F._frame = 9; - } - else if (_wo[6]) { + } else if (_wo[6]) { _indoorList._fwl_4F._frame = 0; - } - else if (_wo[196]) { + } else if (_wo[196]) { _indoorList._fwl_4F._frame = 15; - } - else if (_wo[216]) { + } else if (_wo[216]) { _indoorList._fwl_4F._frame = 14; - } - else if (_wo[236]) { + } else if (_wo[236]) { _indoorList._fwl_4F._frame = 6; - } - else if (_wo[256]) { + } else if (_wo[256]) { _indoorList._fwl_4F._frame = 11; - } - else if (_wo[276]) { + } else if (_wo[276]) { _indoorList._fwl_4F._frame = 12; - } - else if (_wo[296]) { + } else if (_wo[296]) { _indoorList._fwl_4F._frame = 13; } @@ -1114,479 +987,333 @@ void InterfaceMap::drawIndoors() { } if (_wo[22] && _wo[23]) { - } - else if (_wo[22] && _wo[20]) { - } - else if (_wo[17] && _wo[23]) { - } - else if (_wo[17] && _wo[20]) { - } - else if (_wo[8]) { + } else if (_wo[22] && _wo[20]) { + } else if (_wo[17] && _wo[23]) { + } else if (_wo[17] && _wo[20]) { + } else if (_wo[8]) { _indoorList._swl_3F2L._frame = 10; - } - else if (_wo[52]) { + } else if (_wo[52]) { _indoorList._swl_3F2L._frame = 34; } if (_wo[27] || _wo[22] || _wo[15]) { - } - else if (_wo[9]) { + } else if (_wo[9]) { _indoorList._swl_3F4R._frame = 9; - } - else if (_wo[53]) { + } else if (_wo[53]) { _indoorList._swl_3F4R._frame = 33; } if (_wo[22] && _wo[24]) { - } - else if (_wo[22] && _wo[21]) { - } - else if (_wo[19] && _wo[24]) { - } - else if (_wo[19] && _wo[21]) { - } - else if (_wo[14]) { - } - else if (_wo[10]) { + } else if (_wo[22] && _wo[21]) { + } else if (_wo[19] && _wo[24]) { + } else if (_wo[19] && _wo[21]) { + } else if (_wo[14]) { + } else if (_wo[10]) { _indoorList._swl_3F3R._frame = 11; - } - else if (_wo[54]) { + } else if (_wo[54]) { _indoorList._swl_3F3R._frame = 35; } if (_wo[25] || _wo[28] || _wo[20] || _wo[16]) { - } - else if (_wo[97]) { + } else if (_wo[97]) { _indoorList._fwl_3F2L._frame = 24; - } - else if (_wo[55]) { + } else if (_wo[55]) { _indoorList._fwl_3F2L._frame = 33; - } - else if (_wo[137]) { + } else if (_wo[137]) { _indoorList._fwl_3F2L._frame = 26; - } - else if (_wo[157]) { + } else if (_wo[157]) { _indoorList._fwl_3F2L._frame = _overallFrame + 18; - } - else if (_wo[117]) { + } else if (_wo[117]) { _indoorList._fwl_3F2L._frame = 25; - } - else if (_wo[177]) { + } else if (_wo[177]) { _indoorList._fwl_3F2L._frame = 27; - } - else if (_wo[11]) { + } else if (_wo[11]) { _indoorList._fwl_3F2L._frame = 17; - } - else if (_wo[197]) { + } else if (_wo[197]) { _indoorList._fwl_3F2L._frame = 32; - } - else if (_wo[217]) { + } else if (_wo[217]) { _indoorList._fwl_3F2L._frame = 31; - } - else if (_wo[237]) { + } else if (_wo[237]) { _indoorList._fwl_3F2L._frame = 23; - } - else if (_wo[257]) { + } else if (_wo[257]) { _indoorList._fwl_3F2L._frame = 28; - } - else if (_wo[277]) { + } else if (_wo[277]) { _indoorList._fwl_3F2L._frame = 29; - } - else if (_wo[297]) { + } else if (_wo[297]) { _indoorList._fwl_3F2L._frame = 30; } if (_wo[22] && _wo[23]) { - } - else if (_wo[22] && _wo[20]) { - } - else if (_wo[23] && _wo[17]) { - } - else if (_wo[20] && _wo[17]) { - } - else if (_wo[98]) { + } else if (_wo[22] && _wo[20]) { + } else if (_wo[23] && _wo[17]) { + } else if (_wo[20] && _wo[17]) { + } else if (_wo[98]) { _indoorList._fwl_3F1L._frame = 24; - } - else if (_wo[56]) { + } else if (_wo[56]) { _indoorList._fwl_3F1L._frame = 33; - } - else if (_wo[178]) { + } else if (_wo[178]) { _indoorList._fwl_3F1L._frame = 27; - } - else if (_wo[118]) { + } else if (_wo[118]) { _indoorList._fwl_3F1L._frame = 25; - } - else if (_wo[158]) { + } else if (_wo[158]) { _indoorList._fwl_3F1L._frame = _overallFrame + 18; - } - else if (_wo[138]) { + } else if (_wo[138]) { _indoorList._fwl_3F1L._frame = 26; - } - else if (_wo[12]) { + } else if (_wo[12]) { _indoorList._fwl_3F1L._frame = 17; - } - else if (_wo[198]) { + } else if (_wo[198]) { _indoorList._fwl_3F1L._frame = 32; - } - else if (_wo[218]) { + } else if (_wo[218]) { _indoorList._fwl_3F1L._frame = 31; - } - else if (_wo[238]) { + } else if (_wo[238]) { _indoorList._fwl_3F1L._frame = 23; - } - else if (_wo[258]) { + } else if (_wo[258]) { _indoorList._fwl_3F1L._frame = 28; - } - else if (_wo[278]) { + } else if (_wo[278]) { _indoorList._fwl_3F1L._frame = 29; - } - else if (_wo[298]) { + } else if (_wo[298]) { _indoorList._fwl_3F1L._frame = 30; } if (_wo[26] || _wo[29] || _wo[21] || _wo[18]) { - } - else if (_wo[99]) { + } else if (_wo[99]) { _indoorList._fwl_3F2R._frame = 24; - } - else if (_wo[57]) { + } else if (_wo[57]) { _indoorList._fwl_3F2R._frame = 33; - } - else if (_wo[139]) { + } else if (_wo[139]) { _indoorList._fwl_3F2R._frame = 26; - } - else if (_wo[159]) { + } else if (_wo[159]) { _indoorList._fwl_3F2R._frame = _overallFrame + 18; - } - else if (_wo[119]) { + } else if (_wo[119]) { _indoorList._fwl_3F2R._frame = 25; - } - else if (_wo[179]) { + } else if (_wo[179]) { _indoorList._fwl_3F2R._frame = 27; - } - else if (_wo[13]) { + } else if (_wo[13]) { _indoorList._fwl_3F2R._frame = 17; - } - else if (_wo[199]) { + } else if (_wo[199]) { _indoorList._fwl_3F2R._frame = 32; - } - else if (_wo[219]) { + } else if (_wo[219]) { _indoorList._fwl_3F2R._frame = 31; - } - else if (_wo[239]) { + } else if (_wo[239]) { _indoorList._fwl_3F2R._frame = 23; - } - else if (_wo[259]) { + } else if (_wo[259]) { _indoorList._fwl_3F2R._frame = 28; - } - else if (_wo[279]) { + } else if (_wo[279]) { _indoorList._fwl_3F2R._frame = 29; - } - else if (_wo[299]) { + } else if (_wo[299]) { _indoorList._fwl_3F2R._frame = 30; } if (_wo[22] && _wo[24]) { - } - else if (_wo[22] && _wo[21]) { - } - else if (_wo[24] && _wo[19]) { - } - else if (_wo[21] && _wo[19]) { - } - else if (_wo[100]) { + } else if (_wo[22] && _wo[21]) { + } else if (_wo[24] && _wo[19]) { + } else if (_wo[21] && _wo[19]) { + } else if (_wo[100]) { _indoorList._fwl_3F1R._frame = 24; - } - else if (_wo[58]) { + } else if (_wo[58]) { _indoorList._fwl_3F1R._frame = 33; - } - else if (_wo[140]) { + } else if (_wo[140]) { _indoorList._fwl_3F1R._frame = 26; - } - else if (_wo[160]) { + } else if (_wo[160]) { _indoorList._fwl_3F1R._frame = _overallFrame + 18; - } - else if (_wo[120]) { + } else if (_wo[120]) { _indoorList._fwl_3F1R._frame = 25; - } - else if (_wo[180]) { + } else if (_wo[180]) { _indoorList._fwl_3F1R._frame = 27; - } - else if (_wo[14]) { + } else if (_wo[14]) { _indoorList._fwl_3F1R._frame = 17; - } - else if (_wo[200]) { + } else if (_wo[200]) { _indoorList._fwl_3F1R._frame = 32; - } - else if (_wo[220]) { + } else if (_wo[220]) { _indoorList._fwl_3F1R._frame = 31; - } - else if (_wo[240]) { + } else if (_wo[240]) { _indoorList._fwl_3F1R._frame = 23; - } - else if (_wo[260]) { + } else if (_wo[260]) { _indoorList._fwl_3F1R._frame = 28; - } - else if (_wo[280]) { + } else if (_wo[280]) { _indoorList._fwl_3F1R._frame = 29; - } - else if (_wo[300]) { + } else if (_wo[300]) { _indoorList._fwl_3F1R._frame = 30; } if (_wo[22] || _wo[27]) { - } - else if (_wo[101]) { + } else if (_wo[101]) { _indoorList._fwl_3F._frame = 24; - } - else if (_wo[59]) { + } else if (_wo[59]) { _indoorList._fwl_3F._frame = 33; - } - else if (_wo[141]) { + } else if (_wo[141]) { _indoorList._fwl_3F._frame = 26; - } - else if (_wo[161]) { + } else if (_wo[161]) { _indoorList._fwl_3F._frame = _overallFrame + 18; - } - else if (_wo[121]) { + } else if (_wo[121]) { _indoorList._fwl_3F._frame = 25; - } - else if (_wo[181]) { + } else if (_wo[181]) { _indoorList._fwl_3F._frame = 27; - } - else if (_wo[15]) { + } else if (_wo[15]) { _indoorList._fwl_3F._frame = 17; - } - else if (_wo[201]) { + } else if (_wo[201]) { _indoorList._fwl_3F._frame = 32; - } - else if (_wo[221]) { + } else if (_wo[221]) { _indoorList._fwl_3F._frame = 31; - } - else if (_wo[241]) { + } else if (_wo[241]) { _indoorList._fwl_3F._frame = 23; - } - else if (_wo[261]) { + } else if (_wo[261]) { _indoorList._fwl_3F._frame = 28; - } - else if (_wo[281]) { + } else if (_wo[281]) { _indoorList._fwl_3F._frame = 29; - } - else if (_wo[301]) { + } else if (_wo[301]) { _indoorList._fwl_3F._frame = 30; } if (_wo[25] || _wo[28] || _wo[20]) { - } - else if (_wo[16]) { + } else if (_wo[16]) { _indoorList._swl_2F2L._frame = 6; - } - else if (_wo[60]) { + } else if (_wo[60]) { _indoorList._swl_2F2L._frame = 30; } if (_wo[27] || _wo[22]) { - } - else if (_wo[17]) { + } else if (_wo[17]) { _indoorList._swl_2F1L._frame = 4; - } - else if (_wo[61]) { + } else if (_wo[61]) { _indoorList._swl_2F1L._frame = 28; } if (_wo[26] || _wo[29] || _wo[21]) { - } - else if (_wo[18]) { + } else if (_wo[18]) { _indoorList._swl_2F2R._frame = 7; - } - else if (_wo[62]) { + } else if (_wo[62]) { _indoorList._swl_2F2R._frame = 31; } if (_wo[27] || _wo[22]) { - } - else if (_wo[19]) { + } else if (_wo[19]) { _indoorList._swl_2F1R._frame = 5; - } - else if (_wo[63]) { + } else if (_wo[63]) { _indoorList._swl_2F1R._frame = 29; } if (_wo[27] && _wo[25]) { - } - else if (_wo[27] && _wo[28]) { - } - else if (_wo[23] & _wo[25]) { - } - else if (_wo[23] && _wo[28]) { - } - else if (_wo[102]) { + } else if (_wo[27] && _wo[28]) { + } else if (_wo[23] & _wo[25]) { + } else if (_wo[23] && _wo[28]) { + } else if (_wo[102]) { _indoorList._fwl_2F1L._frame = 7; - } - else if (_wo[64]) { + } else if (_wo[64]) { _indoorList._fwl_2F1L._frame = 16; - } - else if (_wo[182]) { + } else if (_wo[182]) { _indoorList._fwl_2F1L._frame = 10; - } - else if (_wo[122]) { + } else if (_wo[122]) { _indoorList._fwl_2F1L._frame = 8; - } - else if (_wo[142]) { + } else if (_wo[142]) { _indoorList._fwl_2F1L._frame = 9; - } - else if (_wo[162]) { + } else if (_wo[162]) { _indoorList._fwl_2F1L._frame = _overallFrame + 1; - } - else if (_wo[20]) { + } else if (_wo[20]) { _indoorList._fwl_2F1L._frame = 0; - } - else if (_wo[202]) { + } else if (_wo[202]) { _indoorList._fwl_2F1L._frame = 15; - } - else if (_wo[222]) { + } else if (_wo[222]) { _indoorList._fwl_2F1L._frame = 14; - } - else if (_wo[242]) { + } else if (_wo[242]) { _indoorList._fwl_2F1L._frame = 6; - } - else if (_wo[262]) { + } else if (_wo[262]) { _indoorList._fwl_2F1L._frame = 11; - } - else if (_wo[282]) { + } else if (_wo[282]) { _indoorList._fwl_2F1L._frame = 12; - } - else if (_wo[302]) { + } else if (_wo[302]) { _indoorList._fwl_2F1L._frame = 13; } if (_wo[27] && _wo[26]) { - } - else if (_wo[27] && _wo[29]) { - } - else if (_wo[24] && _wo[26]) { - } - else if (_wo[24] && _wo[29]) { - } - else if (_wo[103]) { + } else if (_wo[27] && _wo[29]) { + } else if (_wo[24] && _wo[26]) { + } else if (_wo[24] && _wo[29]) { + } else if (_wo[103]) { _indoorList._fwl_2F1R._frame = 7; - } - else if (_wo[65]) { + } else if (_wo[65]) { _indoorList._fwl_2F1R._frame = 16; - } - else if (_wo[183]) { + } else if (_wo[183]) { _indoorList._fwl_2F1R._frame = 10; - } - else if (_wo[123]) { + } else if (_wo[123]) { _indoorList._fwl_2F1R._frame = 8; - } - else if (_wo[143]) { + } else if (_wo[143]) { _indoorList._fwl_2F1R._frame = 9; - } - else if (_wo[163]) { + } else if (_wo[163]) { _indoorList._fwl_2F1R._frame = _overallFrame + 1; - } - else if (_wo[21]) { + } else if (_wo[21]) { _indoorList._fwl_2F1R._frame = 0; - } - else if (_wo[203]) { + } else if (_wo[203]) { _indoorList._fwl_2F1R._frame = 15; - } - else if (_wo[223]) { + } else if (_wo[223]) { _indoorList._fwl_2F1R._frame = 14; - } - else if (_wo[243]) { + } else if (_wo[243]) { _indoorList._fwl_2F1R._frame = 6; - } - else if (_wo[263]) { + } else if (_wo[263]) { _indoorList._fwl_2F1R._frame = 11; - } - else if (_wo[283]) { + } else if (_wo[283]) { _indoorList._fwl_2F1R._frame = 12; - } - else if (_wo[303]) { + } else if (_wo[303]) { _indoorList._fwl_2F1R._frame = 13; } if (_wo[27]) { - - } - else if (_wo[104]) { + } else if (_wo[104]) { _indoorList._fwl_2F._frame = 7; - } - else if (_wo[66]) { + } else if (_wo[66]) { _indoorList._fwl_2F._frame = 16; - } - else if (_wo[184]) { + } else if (_wo[184]) { _indoorList._fwl_2F._frame = 10; - } - else if (_wo[124]) { + } else if (_wo[124]) { _indoorList._fwl_2F._frame = 8; - } - else if (_wo[144]) { + } else if (_wo[144]) { _indoorList._fwl_2F._frame = 9; - } - else if (_wo[164]) { + } else if (_wo[164]) { _indoorList._fwl_2F._frame = _overallFrame + 1; - } - else if (_wo[22]) { + } else if (_wo[22]) { _indoorList._fwl_2F._frame = 0; - } - else if (_wo[204]) { + } else if (_wo[204]) { _indoorList._fwl_2F._frame = 15; - } - else if (_wo[224]) { + } else if (_wo[224]) { _indoorList._fwl_2F._frame = 14; - } - else if (_wo[244]) { + } else if (_wo[244]) { _indoorList._fwl_2F._frame = 6; - } - else if (_wo[264]) { + } else if (_wo[264]) { _indoorList._fwl_2F._frame = 11; - } - else if (_wo[284]) { + } else if (_wo[284]) { _indoorList._fwl_2F._frame = 12; - } - else if (_wo[304]) { + } else if (_wo[304]) { _indoorList._fwl_2F._frame = 13; } if (_wo[27]) { - } - else if (_wo[23]) { + } else if (_wo[23]) { _indoorList._swl_1F1L._frame = 2; - } - else if (_wo[67]) { + } else if (_wo[67]) { _indoorList._swl_1F1L._frame = 26; } if (_wo[27]) { - } - else if (_wo[24]) { + } else if (_wo[24]) { _indoorList._swl_1F1R._frame = 3; - } - else if (_wo[68]) { + } else if (_wo[68]) { _indoorList._swl_1F1R._frame = 27; } if (_wo[28]) { - } - else if (_wo[105] || _wo[25] || _wo[165] || _wo[125] || _wo[185] || _wo[145]) { + } else if (_wo[105] || _wo[25] || _wo[165] || _wo[125] || _wo[185] || _wo[145]) { _indoorList._fwl_1F1L._frame = 0; _indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl1; - } - else if (_wo[69]) { + } else if (_wo[69]) { _indoorList._fwl_1F1L._frame = 9; _indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl2; } if (_wo[29]) { - } - else if (_wo[106] || _wo[26] || _wo[166] || _wo[126] || _wo[186] || _wo[146]) { + } else if (_wo[106] || _wo[26] || _wo[166] || _wo[126] || _wo[186] || _wo[146]) { _indoorList._fwl_1F._frame = 0; _indoorList._fwl_1F._sprites = &map._wallSprites._fwl1; - } - else if (_wo[70]) { + } else if (_wo[70]) { _indoorList._fwl_1F._frame = 9; _indoorList._fwl_1F._sprites = &map._wallSprites._fwl2; } @@ -1597,67 +1324,53 @@ void InterfaceMap::drawIndoors() { _indoorList._fwl_1F1R._frame = 0; else _indoorList._fwl_1F1R._frame = map.mazeData()._wallKind ? 1 : 10; - } - else if (_wo[71]) { + } else if (_wo[71]) { _indoorList._fwl_1F1R._frame = 9; _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[167]) { + } else if (_wo[167]) { _indoorList._fwl_1F1R._frame = _overallFrame + 1; _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[127]) { + } else if (_wo[127]) { _indoorList._fwl_1F1R._frame = 1; _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[147]) { + } else if (_wo[147]) { _indoorList._fwl_1F1R._frame = 2; _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[187]) { + } else if (_wo[187]) { _indoorList._fwl_1F1R._frame = 3; _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[27]) { + } else if (_wo[27]) { _indoorList._fwl_1F1R._frame = 0; _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1; - } - else if (_wo[207]) { + } else if (_wo[207]) { _indoorList._fwl_1F1R._frame = 8; _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[227]) { + } else if (_wo[227]) { _indoorList._fwl_1F1R._frame = 7; _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[247]) { + } else if (_wo[247]) { _indoorList._fwl_1F1R._frame = 6; _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1; - } - else if (_wo[267]) { + } else if (_wo[267]) { _indoorList._fwl_1F1R._frame = 4; _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[287]) { + } else if (_wo[287]) { _indoorList._fwl_1F1R._frame = 5; _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - } - else if (_wo[307]) { + } else if (_wo[307]) { _indoorList._fwl_1F1R._frame = 6; _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; } if (_wo[28]) { _indoorList._swl_0F1L._frame = 0; - } - else if (_wo[72]) { + } else if (_wo[72]) { _indoorList._swl_0F1L._frame = 24; } if (_wo[29]) { _indoorList._swl_0F1R._frame = 1; - } - else if (_wo[73]) { + } else if (_wo[73]) { _indoorList._swl_0F1R._frame = 25; } -- cgit v1.2.3 From 7bfbda627a589817022f12b739ff6cc652ccfee5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 14 Jan 2015 22:10:32 -0500 Subject: XEEN: Initial bugfixes for map loading and fix draw list positions --- engines/xeen/interface.cpp | 2 +- engines/xeen/interface.h | 3 - engines/xeen/interface_map.cpp | 139 +++++++++++++++++++++-------------------- engines/xeen/map.cpp | 7 ++- engines/xeen/screen.cpp | 3 +- 5 files changed, 77 insertions(+), 77 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index deb8761b06..4550dac6d8 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -542,7 +542,7 @@ void Interface::draw3d(bool updateFlag) { Map &map = *_vm->_map; Screen &screen = *_vm->_screen; - if (!screen._windows[11]._enabled) + if (screen._windows[11]._enabled) return; _flipUIFrame = (_flipUIFrame + 1) % 4; diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 4667592b20..df06f5d86b 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -100,9 +100,6 @@ private: void setMazeBits(); void updateAutoMap(); -public: - OutdoorDrawList _outdoorList; - IndoorDrawList _indoorList; public: Interface(XeenEngine *vm); diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index af52178ba1..cc99b3ee86 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -56,31 +56,31 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2 _data[25] = DrawStruct(0, 8, 109); _data[26] = DrawStruct(0, 201, 109); _data[27] = DrawStruct(0, 8, 109); - _data[28] = DrawStruct(1, 65472, 61, 14, SPRFLAG_2000); - _data[29] = DrawStruct(1, 65496, 61, 14, 0); - _data[30] = DrawStruct(1, 65520, 61, 14, 0); + _data[28] = DrawStruct(1, -64, 61, 14, SPRFLAG_2000); + _data[29] = DrawStruct(1, -40, 61, 14, 0); + _data[30] = DrawStruct(1, -16, 61, 14, 0); _data[31] = DrawStruct(1, 8, 61, 14, 0); _data[32] = DrawStruct(1, 128, 61, 14, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000); _data[33] = DrawStruct(1, 104, 61, 14, SPRFLAG_HORIZ_FLIPPED); _data[34] = DrawStruct(1, 80, 61, 14, SPRFLAG_HORIZ_FLIPPED); _data[35] = DrawStruct(1, 56, 61, 14, SPRFLAG_HORIZ_FLIPPED); _data[36] = DrawStruct(1, 32, 61, 14, 0); - _data[37] = DrawStruct(0, 65527, 61, 14, 0); - _data[38] = DrawStruct(0, 65478, 61, 14, 0); + _data[37] = DrawStruct(0, -9, 61, 14, 0); + _data[38] = DrawStruct(0, -58, 61, 14, 0); _data[39] = DrawStruct(0, 40, 61, 14, 0); - _data[40] = DrawStruct(0, 65454, 61, 14, 0); + _data[40] = DrawStruct(0, -82, 61, 14, 0); _data[41] = DrawStruct(0, 64, 61, 14, 0); - _data[42] = DrawStruct(0, 65495, 61, 14, 0); - _data[43] = DrawStruct(0, 65510, 61, 14, 0); - _data[44] = DrawStruct(0, 65502, 61, 14, 0); - _data[45] = DrawStruct(0, 65520, 61, 14, 0); + _data[42] = DrawStruct(0, -41, 61, 14, 0); + _data[43] = DrawStruct(0, -26, 61, 14, 0); + _data[44] = DrawStruct(0, -34, 61, 14, 0); + _data[45] = DrawStruct(0, -16, 61, 14, 0); _data[46] = DrawStruct(0, 23, 61, 14, 0); _data[47] = DrawStruct(0, 16, 61, 14, 0); - _data[48] = DrawStruct(0, 65478, 61, 14, 0); + _data[48] = DrawStruct(0, -58, 61, 14, 0); _data[49] = DrawStruct(0, 40, 61, 14, 0); - _data[50] = DrawStruct(0, 65519, 61, 14, 0); - _data[51] = DrawStruct(0, 65535, 58, 14, 0); - _data[52] = DrawStruct(0, 65527, 58, 14, 0); + _data[50] = DrawStruct(0, -17, 61, 14, 0); + _data[51] = DrawStruct(0, -1, 58, 14, 0); + _data[52] = DrawStruct(0, -9, 58, 14, 0); _data[53] = DrawStruct(0, 72, 58, 12, 0); _data[54] = DrawStruct(0, 72, 58, 12, SPRFLAG_HORIZ_FLIPPED); _data[55] = DrawStruct(0, 69, 63, 12, 0); @@ -89,21 +89,21 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2 _data[58] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED); _data[59] = DrawStruct(0, 80, 57, 12, 0); _data[60] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED); - _data[61] = DrawStruct(2, 65525, 54, 8, 0); - _data[62] = DrawStruct(1, 65515, 54, 11, 0); + _data[61] = DrawStruct(2, -11, 54, 8, 0); + _data[62] = DrawStruct(1, -21, 54, 11, 0); _data[63] = DrawStruct(2, 165, 54, 8, SPRFLAG_HORIZ_FLIPPED); _data[64] = DrawStruct(1, 86, 54, 11, SPRFLAG_HORIZ_FLIPPED); _data[65] = DrawStruct(1, 33, 54, 11, 0); - _data[66] = DrawStruct(0, 65528, 54, 12, 0); - _data[67] = DrawStruct(0, 65463, 54, 12, 0); + _data[66] = DrawStruct(0, -8, 54, 12, 0); + _data[67] = DrawStruct(0, -73, 54, 12, 0); _data[68] = DrawStruct(0, 57, 54, 12, 0); - _data[69] = DrawStruct(0, 65471, 54, 12, 0); - _data[70] = DrawStruct(0, 65455, 54, 12, 0); + _data[69] = DrawStruct(0, -65, 54, 12, 0); + _data[70] = DrawStruct(0, -81, 54, 12, 0); _data[71] = DrawStruct(0, 49, 54, 12, 0); _data[72] = DrawStruct(0, 65, 54, 12, 0); - _data[73] = DrawStruct(0, 65512, 54, 12, 0); + _data[73] = DrawStruct(0, -24, 54, 12, 0); _data[74] = DrawStruct(0, 9, 50, 12, 0); - _data[75] = DrawStruct(0, 65528, 50, 12, 0); + _data[75] = DrawStruct(0, -8, 50, 12, 0); _data[76] = DrawStruct(0, 72, 53, 8, 0); _data[77] = DrawStruct(0, 72, 53, 8, SPRFLAG_HORIZ_FLIPPED); _data[78] = DrawStruct(0, 77, 58, 8, 0); @@ -115,14 +115,14 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2 _data[84] = DrawStruct(2, 8, 40); _data[85] = DrawStruct(2, 146, 40, 0, SPRFLAG_HORIZ_FLIPPED); _data[86] = DrawStruct(1, 32, 40, 6, 0); - _data[87] = DrawStruct(0, 65529, 30, 7, 0); - _data[88] = DrawStruct(0, 65424, 30, 7, SPRFLAG_2000); + _data[87] = DrawStruct(0, -7, 30, 7, 0); + _data[88] = DrawStruct(0, -112, 30, 7, SPRFLAG_2000); _data[89] = DrawStruct(0, 98, 30, 7, SPRFLAG_2000); - _data[90] = DrawStruct(0, 65424, 30, 8, SPRFLAG_2000); + _data[90] = DrawStruct(0, -112, 30, 8, SPRFLAG_2000); _data[91] = DrawStruct(0, 98, 30, 8, SPRFLAG_2000); - _data[92] = DrawStruct(0, 65498, 30, 8, 0); + _data[92] = DrawStruct(0, -38, 30, 8, 0); _data[93] = DrawStruct(0, 25, 30, 8, 0); - _data[94] = DrawStruct(0, 65529, 30, 8, 0); + _data[94] = DrawStruct(0, -7, 30, 8, 0); _data[95] = DrawStruct(0, 72, 48, 4, 0); _data[96] = DrawStruct(0, 72, 48, 4, SPRFLAG_HORIZ_FLIPPED); _data[97] = DrawStruct(0, 85, 53, 4, 0); @@ -134,22 +134,22 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2 _data[103] = DrawStruct(0, 8, 24); _data[104] = DrawStruct(0, 169, 24, 0, SPRFLAG_HORIZ_FLIPPED); _data[105] = DrawStruct(1, 32, 24); - _data[106] = DrawStruct(0, 65513, 40, 0, SPRFLAG_2000); + _data[106] = DrawStruct(0, -23, 40, 0, SPRFLAG_2000); _data[107] = DrawStruct(0, 200, 40, 0, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000); _data[108] = DrawStruct(0, 8, 47); _data[109] = DrawStruct(0, 169, 47, 0, SPRFLAG_HORIZ_FLIPPED); - _data[110] = DrawStruct(1, 65480, 65532, 32768, SPRFLAG_4000 | SPRFLAG_2000); - _data[111] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); - _data[112] = DrawStruct(0, 65469, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[110] = DrawStruct(1, -56, -4, 0x8000, SPRFLAG_4000 | SPRFLAG_2000); + _data[111] = DrawStruct(0, -5, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[112] = DrawStruct(0, -67, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); _data[113] = DrawStruct(0, 44, 73); _data[114] = DrawStruct(0, 44, 73); _data[115] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); _data[116] = DrawStruct(0, 169, 73); _data[117] = DrawStruct(0, 169, 73); - _data[118] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[118] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); _data[119] = DrawStruct(0, 110, 73); _data[120] = DrawStruct(0, 110, 73); - _data[121] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[121] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); _data[122] = DrawStruct(0, 110, 73); _data[123] = DrawStruct(0, 110, 73); _data[124] = DrawStruct(0, 72, 43); @@ -232,31 +232,31 @@ IndoorDrawList::IndoorDrawList() : _data[43] = DrawStruct(14, 152, 60); _data[44] = DrawStruct(8, 176, 60); _data[45] = DrawStruct(8, 200, 60); - _data[46] = DrawStruct(0, 65472, 61, 14, 0); - _data[47] = DrawStruct(0, 65496, 61, 14, 0); - _data[48] = DrawStruct(0, 65520, 61, 14, 0); + _data[46] = DrawStruct(0, -64, 61, 14, 0); + _data[47] = DrawStruct(0, -40, 61, 14, 0); + _data[48] = DrawStruct(0, -16, 61, 14, 0); _data[49] = DrawStruct(0, 8, 61, 14, 0); _data[50] = DrawStruct(0, 32, 61, 14, 0); _data[51] = DrawStruct(0, 56, 61, 14, 0); _data[52] = DrawStruct(0, 80, 61, 14, 0); _data[53] = DrawStruct(0, 104, 61, 14, 0); _data[54] = DrawStruct(0, 128, 61, 14, 0); - _data[55] = DrawStruct(0, 65527, 58, 14, 0); - _data[56] = DrawStruct(0, 65502, 58, 14, 0); + _data[55] = DrawStruct(0, -9, 58, 14, 0); + _data[56] = DrawStruct(0, -34, 58, 14, 0); _data[57] = DrawStruct(0, 16, 58, 14, 0); - _data[58] = DrawStruct(0, 65478, 58, 14, 0); + _data[58] = DrawStruct(0, -58, 58, 14, 0); _data[59] = DrawStruct(0, 40, 58, 14, 0); - _data[60] = DrawStruct(0, 65495, 58, 14, 0); - _data[61] = DrawStruct(0, 65510, 58, 14, 0); - _data[62] = DrawStruct(0, 65502, 58, 14, 0); - _data[63] = DrawStruct(0, 65520, 58, 14, 0); + _data[60] = DrawStruct(0, -41, 58, 14, 0); + _data[61] = DrawStruct(0, -26, 58, 14, 0); + _data[62] = DrawStruct(0, -34, 58, 14, 0); + _data[63] = DrawStruct(0, -16, 58, 14, 0); _data[64] = DrawStruct(0, 23, 58, 14, 0); _data[65] = DrawStruct(0, 16, 58, 14, 0); - _data[66] = DrawStruct(0, 65478, 58, 14, 0); + _data[66] = DrawStruct(0, -58, 58, 14, 0); _data[67] = DrawStruct(0, 40, 58, 14, 0); - _data[68] = DrawStruct(0, 65519, 58, 14, 0); - _data[69] = DrawStruct(0, 65535, 58, 14, 0); - _data[70] = DrawStruct(0, 65527, 58, 14, 0); + _data[68] = DrawStruct(0, -17, 58, 14, 0); + _data[69] = DrawStruct(0, -1, 58, 14, 0); + _data[70] = DrawStruct(0, -9, 58, 14, 0); _data[71] = DrawStruct(14, 8, 58); _data[72] = DrawStruct(12, 8, 55); _data[73] = DrawStruct(10, 32, 52); @@ -273,26 +273,26 @@ IndoorDrawList::IndoorDrawList() : _data[84] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED); _data[85] = DrawStruct(0, 80, 57, 12, 0); _data[86] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED); - _data[87] = DrawStruct(7, 65512, 52, 0, SPRFLAG_2000); + _data[87] = DrawStruct(7, -24, 52, 0, SPRFLAG_2000); _data[88] = DrawStruct(7, 32, 52); _data[89] = DrawStruct(7, 88, 52); _data[90] = DrawStruct(0, 144, 52); _data[91] = DrawStruct(0, 200, 52, 0, SPRFLAG_2000); - _data[92] = DrawStruct(0, 65457, 52, 11, SPRFLAG_2000); - _data[93] = DrawStruct(0, 65509, 52, 11, 0); + _data[92] = DrawStruct(0, -79, 52, 11, SPRFLAG_2000); + _data[93] = DrawStruct(0, -27, 52, 11, 0); _data[94] = DrawStruct(0, 32, 52, 11, 0); _data[95] = DrawStruct(0, 89, 52, 11, 0); _data[96] = DrawStruct(0, 145, 52, 11, SPRFLAG_2000); - _data[97] = DrawStruct(0, 65528, 50, 12, 0); - _data[98] = DrawStruct(0, 65471, 50, 12, 0); + _data[97] = DrawStruct(0, -8, 50, 12, 0); + _data[98] = DrawStruct(0, -65, 50, 12, 0); _data[99] = DrawStruct(0, 49, 50, 12, 0); - _data[100] = DrawStruct(0, 65471, 50, 12, 0); - _data[101] = DrawStruct(0, 65455, 50, 12, 0); + _data[100] = DrawStruct(0, -65, 50, 12, 0); + _data[101] = DrawStruct(0, -81, 50, 12, 0); _data[102] = DrawStruct(0, 49, 50, 12, 0); _data[103] = DrawStruct(0, 65, 50, 12, 0); - _data[104] = DrawStruct(0, 65512, 50, 12, 0); + _data[104] = DrawStruct(0, -24, 50, 12, 0); _data[105] = DrawStruct(0, 9, 50, 12, 0); - _data[106] = DrawStruct(0, 65528, 50, 12, 0); + _data[106] = DrawStruct(0, -8, 50, 12, 0); _data[107] = DrawStruct(7, 8, 48); _data[108] = DrawStruct(7, 64, 40); _data[109] = DrawStruct(6, 144, 40, 0, SPRFLAG_HORIZ_FLIPPED); @@ -305,20 +305,20 @@ IndoorDrawList::IndoorDrawList() : _data[116] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED); _data[117] = DrawStruct(0, 94, 52, 8, 0); _data[118] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED); - _data[119] = DrawStruct(6, 65496, 40, 0, SPRFLAG_2000); + _data[119] = DrawStruct(6, -40, 40, 0, SPRFLAG_2000); _data[120] = DrawStruct(6, 64, 40); _data[121] = DrawStruct(0, 168, 40, 0, SPRFLAG_2000); - _data[122] = DrawStruct(0, 65464, 40, 6, SPRFLAG_2000); + _data[122] = DrawStruct(0, -72, 40, 6, SPRFLAG_2000); _data[123] = DrawStruct(0, 32, 40, 6, 0); _data[124] = DrawStruct(0, 137, 40, 6, SPRFLAG_2000); - _data[125] = DrawStruct(0, 65529, 25, 7, 0); - _data[126] = DrawStruct(0, 65424, 25, 7, SPRFLAG_2000); + _data[125] = DrawStruct(0, -7, 25, 7, 0); + _data[126] = DrawStruct(0, -112, 25, 7, SPRFLAG_2000); _data[127] = DrawStruct(0, 98, 25, 7, SPRFLAG_2000); - _data[128] = DrawStruct(0, 65424, 29, 8, SPRFLAG_2000); + _data[128] = DrawStruct(0, -112, 29, 8, SPRFLAG_2000); _data[129] = DrawStruct(0, 98, 29, 8, SPRFLAG_2000); - _data[130] = DrawStruct(0, 65498, 29, 8, 0); + _data[130] = DrawStruct(0, -38, 29, 8, 0); _data[131] = DrawStruct(0, 25, 29, 8, 0); - _data[132] = DrawStruct(0, 65529, 29, 8, 0); + _data[132] = DrawStruct(0, -7, 29, 8, 0); _data[133] = DrawStruct(6, 32, 24); _data[134] = DrawStruct(0, 168, 24, 0, SPRFLAG_HORIZ_FLIPPED); _data[135] = DrawStruct(0, 72, 48, 4, 0); @@ -329,23 +329,23 @@ IndoorDrawList::IndoorDrawList() : _data[140] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED); _data[141] = DrawStruct(0, 106, 47, 4, 0); _data[142] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED); - _data[143] = DrawStruct(0, 65400, 24, 0, SPRFLAG_2000); + _data[143] = DrawStruct(0, -136, 24, 0, SPRFLAG_2000); _data[144] = DrawStruct(0, 8, 12); _data[145] = DrawStruct(0, 32, 24); _data[146] = DrawStruct(0, 200, 12, 0, SPRFLAG_HORIZ_FLIPPED); _data[147] = DrawStruct(0, 200, 24, 0, SPRFLAG_2000); _data[148] = DrawStruct(0, 32, 24); - _data[149] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); - _data[150] = DrawStruct(0, 65469, 10, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[149] = DrawStruct(0, -5, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[150] = DrawStruct(0, -67, 10, 0, SPRFLAG_4000 | SPRFLAG_2000); _data[151] = DrawStruct(0, 44, 73); _data[152] = DrawStruct(0, 44, 73); _data[153] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); _data[154] = DrawStruct(0, 169, 73); _data[155] = DrawStruct(0, 169, 73); - _data[156] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[156] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); _data[157] = DrawStruct(0, 110, 73); _data[158] = DrawStruct(0, 110, 73); - _data[159] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[159] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); _data[160] = DrawStruct(0, 110, 73); _data[161] = DrawStruct(0, 110, 73); _data[162] = DrawStruct(0, 72, 43); @@ -576,7 +576,8 @@ void InterfaceMap::drawIndoors() { map.getCell(DRAW_NUMBERS[cellIndex]); DrawStruct &drawStruct = _indoorList[3 + cellIndex]; - drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId]; + if (!map._surfaceSprites[map._currentSurfaceId].empty()) + drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId]; surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; if (surfaceId == 5 || surfaceId == 12) { diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index e410333d0d..507e4fc422 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1157,9 +1157,10 @@ void Map::load(int mapId) { indoorList._fwl_1F._sprites = &_wallSprites._fwl1; indoorList._fwl_1F1R._sprites = &_wallSprites._fwl1; - indoorList._fwl_1F1L._sprites = &_wallSprites._fwl1; - - indoorList._horizon._sprites = &_groundSprites; + indoorList._fwl_1F1L._sprites = &_wallSprites._fwl1; + indoorList._horizon._sprites = &_wallSprites._fwl1; + + indoorList._ground._sprites = &_groundSprites; // Down show horizon for certain maps if (_vm->_files->_isDarkCc) { diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 783f1ffbf4..7b6f972268 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -275,7 +275,8 @@ void Screen::update() { } void Screen::addDirtyRect(const Common::Rect &r) { - assert(r.isValidRect() && r.width() > 0 && r.height() > 0 + assert(r.isValidRect() && r.width() > 0 && r.height() > 0 + && r.left >= 0 && r.top >= 0 && r.right <= SCREEN_WIDTH && r.bottom <= SCREEN_HEIGHT); _dirtyRects.push_back(r); } -- cgit v1.2.3 From 7e4580a2203ef63a129a9c2992c5cd1210b5bf80 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 14 Jan 2015 22:42:09 -0500 Subject: XEEN: Add cropping support to sprite drawing --- engines/xeen/sprites.cpp | 49 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 74f2b1d04a..df1debab21 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -110,10 +110,15 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi if (lineLength == 0) { // Skip the specified number of scan lines yPos += f.readByte(); + } else if ((destPos.y + yPos) < 0) { + // Skip over the bytes of the line + f.skip(lineLength); } else { // Skip the transparent pixels at the beginning of the scan line int xPos = f.readByte() + xOffset; ++byteCount; byte *destP = (byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos); + const byte *lineStartP = (const byte *)dest.getBasePtr(0, destPos.y + yPos); + const byte *lineEndP = (const byte *)dest.getBasePtr(dest.w, destPos.y + yPos); while (byteCount < lineLength) { // The next byte is an opcode that determines what @@ -128,14 +133,23 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi case 0: // The following len + 1 bytes are stored as indexes into the color table. case 1: // The following len + 33 bytes are stored as indexes into the color table. for (int i = 0; i < opcode + 1; ++i, ++xPos) { - *destP++ = f.readByte(); ++byteCount; + byte b = f.readByte(); + if (destP < lineStartP || destP >= lineEndP) + ++destP; + else + *destP++ = b; + ++byteCount; } break; case 2: // The following byte is an index into the color table, draw it len + 3 times. opr1 = f.readByte(); ++byteCount; - for (int i = 0; i < len + 3; ++i, ++xPos) - *destP++ = opr1; + for (int i = 0; i < len + 3; ++i, ++xPos) { + if (destP < lineStartP || destP >= lineEndP) + ++destP; + else + *destP++ = opr1; + } break; case 3: // Stream copy command. @@ -143,8 +157,13 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi pos = f.pos(); f.seek(-opr1, SEEK_CUR); - for (int i = 0; i < len + 4; ++i, ++xPos) - *destP++ = f.readByte(); + for (int i = 0; i < len + 4; ++i, ++xPos) { + byte b = f.readByte(); + if (destP < lineStartP || destP >= lineEndP) + ++destP; + else + *destP++ = b; + } f.seek(pos, SEEK_SET); break; @@ -153,8 +172,12 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi opr1 = f.readByte(); ++byteCount; opr2 = f.readByte(); ++byteCount; for (int i = 0; i < len + 2; ++i, xPos += 2) { - *destP++ = opr1; - *destP++ = opr2; + if (destP < lineStartP || destP >= (lineEndP - 1)) { + destP += 2; + } else { + *destP++ = opr1; + *destP++ = opr2; + } } break; @@ -171,7 +194,10 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi opr1 = f.readByte(); ++byteCount; for (int i = 0; i < len + 3; ++i, ++xPos) { - *destP++ = opr1; + if (destP < lineStartP || destP >= lineEndP) + ++destP; + else + *destP++ = opr1; opr1 += patternSteps[cmd + (i % 2)]; } break; @@ -183,9 +209,12 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi assert(byteCount == lineLength); } } - - dest.addDirtyRect(Common::Rect(destPos.x + xOffset, destPos.y + yOffset, + + Common::Rect r(Common::Rect(destPos.x + xOffset, destPos.y + yOffset, destPos.x + xOffset + width, destPos.y + yOffset + height)); + r.clip(Common::Rect(0, 0, dest.w, dest.h)); + if (!r.isEmpty()) + dest.addDirtyRect(r); } void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, int flags) const { -- cgit v1.2.3 From 3e7163769d1a28721dc000a9ef0a142731705ad4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 15 Jan 2015 08:33:43 -0500 Subject: XEEN: Beginnings of setIndoorMonsters implementation --- engines/xeen/combat.cpp | 9 ++++-- engines/xeen/combat.h | 5 ++- engines/xeen/interface_map.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++ engines/xeen/interface_map.h | 5 +++ engines/xeen/map.cpp | 1 + engines/xeen/map.h | 3 +- engines/xeen/resources.cpp | 21 +++++++++++++ engines/xeen/resources.h | 6 ++++ 8 files changed, 117 insertions(+), 4 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index b3ef4fda71..077205394e 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -25,8 +25,9 @@ namespace Xeen { -Combat::Combat(XeenEngine *vm): _vm(vm) { - _attackMon1 = _attackMon2 = _attackMon3 = 0; +Combat::Combat(XeenEngine *vm): _vm(vm), _attackMon1(_attackMonsters[0]), + _attackMon2(_attackMonsters[1]), _attackMon3(_attackMonsters[2]) { + Common::fill(&_attackMonsters[0], &_attackMonsters[26], 0); Common::fill(&_charsArray1[0], &_charsArray1[12], 0); Common::fill(&_monPow[0], &_monPow[12], 0); Common::fill(&_monsterScale[0], &_monsterScale[12], 0); @@ -35,4 +36,8 @@ Combat::Combat(XeenEngine *vm): _vm(vm) { Common::fill(&_shooting[0], &_shooting[6], 0); } +void Combat::clear() { + Common::fill(&_attackMonsters[0], &_attackMonsters[26], -1); +} + } // End of namespace Xeen diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 24a358716f..4ead4047cf 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -33,15 +33,18 @@ class Combat { private: XeenEngine *_vm; public: + int _attackMonsters[26]; int _charsArray1[12]; bool _monPow[12]; int _monsterScale[12]; int _elemPow[12]; int _elemScale[12]; bool _shooting[6]; - int _attackMon1, _attackMon2, _attackMon3; + int &_attackMon1, _attackMon2, _attackMon3; public: Combat(XeenEngine *vm); + + void clear(); }; } // End of namespace Xeen diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index cc99b3ee86..f4c0dc0845 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -371,9 +371,80 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) { _isShooting = false; _charsShooting = false; _objNumber = 0; + _combatFloatCounter = 0; } void InterfaceMap::setIndoorsMonsters() { + Combat &combat = *_vm->_combat; + Map &map = *_vm->_map; + Direction dir = _vm->_party._mazeDirection; + const int INDOOR_MONSTERS_Y[4] = { 2, 34, 53, 59 }; + + combat.clear(); + for (uint monsterIdx = 0; monsterIdx < map._mobData._monsters.size(); ++monsterIdx) { + MazeMonster &monster = map._mobData._monsters[monsterIdx]; + SpriteResource *sprites = monster._sprites; + int frame = monster._frame; + + if (frame >= 8) { + sprites = monster._attackSprites; + frame -= 8; + } + + // The following long sequence sets up monsters in the various positions + if (monster._position.x == SCREEN_POSITIONING_X[dir][2] && + monster._position.y == SCREEN_POSITIONING_Y[dir][2]) { + monster._field4 = 1; + if (combat._attackMonsters[0] == -1) { + combat._attackMonsters[0] = monsterIdx; + setMonsterSprite(_indoorList[156], monster, sprites, frame, INDOOR_MONSTERS_Y[0]); + } else if (combat._attackMonsters[1] == -1) { + combat._attackMonsters[1] = monsterIdx; + setMonsterSprite(_indoorList[150], monster, sprites, frame, INDOOR_MONSTERS_Y[0]); + } else if (combat._attackMonsters[2] == -1) { + combat._attackMonsters[2] = monsterIdx; + setMonsterSprite(_indoorList[153], monster, sprites, frame, INDOOR_MONSTERS_Y[0]); + } + } + + if (monster._position.x == SCREEN_POSITIONING_X[dir][7] && + monster._position.y == SCREEN_POSITIONING_Y[dir][7]) { + monster._field4 = 1; + if (!_wo[27]) { + if (combat._attackMonsters[3] == -1) { + combat._attackMonsters[3] = monsterIdx; + setMonsterSprite(_indoorList[132], monster, sprites, frame, INDOOR_MONSTERS_Y[1]); + } else if (combat._attackMonsters[4] == -1) { + combat._attackMonsters[4] = monsterIdx; + setMonsterSprite(_indoorList[130], monster, sprites, frame, INDOOR_MONSTERS_Y[1]); + } else if (combat._attackMonsters[2] == -1) { + combat._attackMonsters[5] = monsterIdx; + setMonsterSprite(_indoorList[131], monster, sprites, frame, INDOOR_MONSTERS_Y[1]); + } + } + } + } +} + +void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, SpriteResource *sprites, + int frame, int defaultY) { + MonsterStruct &monsterData = _vm->_map->_monsterData[monster._spriteId]; + bool flying = monsterData._flying; + + _indoorList[156]._frame = frame; + _indoorList[156]._sprites = sprites; + _indoorList[156]._y = defaultY; + + if (flying) { + _indoorList[156]._x = COMBAT_FLOAT_X[_combatFloatCounter]; + _indoorList[156]._y = COMBAT_FLOAT_Y[_combatFloatCounter]; + } else { + _indoorList[156]._x = 0; + } + + _indoorList[156]._flags &= SPRFLAG_HORIZ_FLIPPED | SPRFLAG_4000 | SPRFLAG_2000; + if (monster._effect2) + _indoorList[156]._flags = MONSTER_EFFECT_FLAGS[monster._effect2][monster._effect3]; } diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 01cd1d2c48..ea40c30a79 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -24,6 +24,7 @@ #define XEEN_INTERFACE_MAP_H #include "common/scummsys.h" +#include "xeen/map.h" #include "xeen/screen.h" namespace Xeen { @@ -81,8 +82,12 @@ public: class InterfaceMap { private: XeenEngine *_vm; + int _combatFloatCounter; void initDrawStructs(); + + void setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, + SpriteResource *sprites, int frame, int defaultY); protected: byte _wp[20]; byte _wo[308]; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 507e4fc422..c136dee534 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -638,6 +638,7 @@ MazeMonster::MazeMonster() { _frame = 0; _id = 0; _spriteId = 0; + _field4 = 0; _hp = 0; _effect1 = _effect2 = 0; _effect3 = 0; diff --git a/engines/xeen/map.h b/engines/xeen/map.h index faffe97c97..821922bd7f 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -250,6 +250,7 @@ struct MazeMonster { int _frame; int _id; int _spriteId; + int _field4; int _hp; int _effect1, _effect2; int _effect3; @@ -352,7 +353,6 @@ private: XeenEngine *_vm; MazeData _mazeData[9]; Common::String _mazeName; - MonsterData _monsterData; SpriteResource _wallPicSprites; int _townPortalSide; int _sideObj; @@ -365,6 +365,7 @@ private: public: bool _isOutdoors; MonsterObjectData _mobData; + MonsterData _monsterData; MazeEvents _events; HeadData _headData; AnimationInfo _animationInfo; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index e56ad1656e..87540b8df4 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -445,5 +445,26 @@ const int DRAW_FRAMES[25][2] = { { 1, 1 } }; +const int COMBAT_FLOAT_X[8] = { -2, -1, 0, 1, 2, 1, 0, -1 }; + +const int COMBAT_FLOAT_Y[8] = { -2, 0, 2, 0, -1, 0, 2, 0 }; + +const int MONSTER_EFFECT_FLAGS[15][8] = { + { 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10A, 0x10B }, + { 0x10C, 0x10D, 0x10E, 0x10F, 0x0, 0x0, 0x0, 0x0 }, + { 0x110, 0x111, 0x112, 0x113, 0x0, 0x0, 0x0, 0x0 }, + { 0x114, 0x115, 0x116, 0x117, 0x0, 0x0, 0x0, 0x0 }, + { 0x200, 0x201, 0x202, 0x203, 0x0, 0x0, 0x0, 0x0 }, + { 0x300, 0x301, 0x302, 0x303, 0x400, 0x401, 0x402, 0x403 }, + { 0x500, 0x501, 0x502, 0x503, 0x0, 0x0, 0x0, 0x0 }, + { 0x600, 0x601, 0x602, 0x603, 0x0, 0x0, 0x0, 0x0 }, + { 0x604, 0x605, 0x606, 0x607, 0x608, 0x609, 0x60A, 0x60B }, + { 0x60C, 0x60D, 0x60E, 0x60F, 0x0, 0x0, 0x0, 0x0 }, + { 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100 }, + { 0x101, 0x101, 0x101, 0x101, 0x101, 0x101, 0x101, 0x101 }, + { 0x102, 0x102, 0x102, 0x102, 0x102, 0x102, 0x102, 0x102 }, + { 0x103, 0x103, 0x103, 0x103, 0x103, 0x103, 0x103, 0x103 }, + { 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108 } +}; } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index bed9569163..2160d55c53 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -94,6 +94,12 @@ extern const int DRAW_NUMBERS[25]; extern const int DRAW_FRAMES[25][2]; +extern const int COMBAT_FLOAT_X[8]; + +extern const int COMBAT_FLOAT_Y[8]; + +extern const int MONSTER_EFFECT_FLAGS[15][8]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From ce3cb6f1dbc32ca682279a9021cbbc8da1a1f30a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 15 Jan 2015 20:39:52 -0500 Subject: XEEN: Finished setIndoorsMonsters --- engines/xeen/combat.cpp | 3 +- engines/xeen/combat.h | 1 - engines/xeen/interface.cpp | 8 +- engines/xeen/interface_map.cpp | 216 ++++++++++++++++++++++++++++++++++++++--- engines/xeen/map.cpp | 2 +- engines/xeen/map.h | 2 +- 6 files changed, 212 insertions(+), 20 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 077205394e..98dff4c6d9 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -25,8 +25,7 @@ namespace Xeen { -Combat::Combat(XeenEngine *vm): _vm(vm), _attackMon1(_attackMonsters[0]), - _attackMon2(_attackMonsters[1]), _attackMon3(_attackMonsters[2]) { +Combat::Combat(XeenEngine *vm): _vm(vm) { Common::fill(&_attackMonsters[0], &_attackMonsters[26], 0); Common::fill(&_charsArray1[0], &_charsArray1[12], 0); Common::fill(&_monPow[0], &_monPow[12], 0); diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 4ead4047cf..c64741b59e 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -40,7 +40,6 @@ public: int _elemPow[12]; int _elemScale[12]; bool _shooting[6]; - int &_attackMon1, _attackMon2, _attackMon3; public: Combat(XeenEngine *vm); diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 4550dac6d8..eb607db7a2 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -631,7 +631,7 @@ void Interface::draw3d(bool updateFlag) { ds2._sprites = nullptr; if (combat._charsArray1[idx]) { - int posIndex= combat._attackMon2 && !combat._attackMon3 ? 1 : 0; + int posIndex= combat._attackMonsters[1] && !combat._attackMonsters[2] ? 1 : 0; --combat._charsArray1[idx]; if (combat._monPow[idx]) { @@ -671,7 +671,7 @@ void Interface::draw3d(bool updateFlag) { // Handle attacking monsters int monsterIndex = 0; - if (combat._attackMon1 != -1 && map._mobData._monsters[combat._attackMon1]._frame >= 0) { + if (combat._attackMonsters[0] != -1 && map._mobData._monsters[combat._attackMonsters[0]]._frame >= 0) { _indoorList[159] = _indoorList[156]; _indoorList[160] = _indoorList[157]; _indoorList[161] = _indoorList[158]; @@ -679,7 +679,7 @@ void Interface::draw3d(bool updateFlag) { _indoorList[156]._sprites = nullptr; _indoorList[157]._sprites = nullptr; monsterIndex = 1; - } else if (combat._attackMon2 != -1 && map._mobData._monsters[combat._attackMon2]._frame >= 0) { + } else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 0) { _indoorList[159] = _indoorList[150]; _indoorList[160] = _indoorList[151]; _indoorList[161] = _indoorList[152]; @@ -687,7 +687,7 @@ void Interface::draw3d(bool updateFlag) { _indoorList[151]._sprites = nullptr; _indoorList[150]._sprites = nullptr; monsterIndex = 2; - } else if (combat._attackMon3 != -1 && map._mobData._monsters[combat._attackMon3]._frame >= 0) { + } else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 0) { _indoorList[159] = _indoorList[153]; _indoorList[160] = _indoorList[154]; _indoorList[161] = _indoorList[155]; diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index f4c0dc0845..ba5cdbc7d0 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -394,7 +394,7 @@ void InterfaceMap::setIndoorsMonsters() { // The following long sequence sets up monsters in the various positions if (monster._position.x == SCREEN_POSITIONING_X[dir][2] && monster._position.y == SCREEN_POSITIONING_Y[dir][2]) { - monster._field4 = 1; + monster._isAttacking = true; if (combat._attackMonsters[0] == -1) { combat._attackMonsters[0] = monsterIdx; setMonsterSprite(_indoorList[156], monster, sprites, frame, INDOOR_MONSTERS_Y[0]); @@ -409,7 +409,7 @@ void InterfaceMap::setIndoorsMonsters() { if (monster._position.x == SCREEN_POSITIONING_X[dir][7] && monster._position.y == SCREEN_POSITIONING_Y[dir][7]) { - monster._field4 = 1; + monster._isAttacking = true; if (!_wo[27]) { if (combat._attackMonsters[3] == -1) { combat._attackMonsters[3] = monsterIdx; @@ -423,6 +423,201 @@ void InterfaceMap::setIndoorsMonsters() { } } } + + if (monster._position.x == SCREEN_POSITIONING_X[dir][5] && + monster._position.y == SCREEN_POSITIONING_Y[dir][5]) { + if (_wo[27] && _wo[25]) { + } else if (_wo[27] && _wo[28]) { + } else if (_wo[23] & _wo[25]) { + } else if (_wo[23] && _wo[28]) { + } else { + monster._isAttacking = true; + + if (combat._attackMonsters[12] == -1) { + combat._attackMonsters[12] = monsterIdx; + setMonsterSprite(_indoorList[128], monster, sprites, frame, INDOOR_MONSTERS_Y[1]); + } + } + } + + if (monster._position.x == SCREEN_POSITIONING_X[dir][9] && + monster._position.y == SCREEN_POSITIONING_Y[dir][9]) { + if (_wo[27] && _wo[26]) { + } else if (_wo[27] && _wo[29]) { + } else if (_wo[24] & _wo[26]) { + } else if (_wo[24] && _wo[29]) { + } else { + monster._isAttacking = true; + + if (combat._attackMonsters[13] == -1) { + combat._attackMonsters[13] = monsterIdx; + setMonsterSprite(_indoorList[129], monster, sprites, frame, INDOOR_MONSTERS_Y[1]); + } + } + } + + if (monster._position.x == SCREEN_POSITIONING_X[dir][14] && + monster._position.y == SCREEN_POSITIONING_Y[dir][14]) { + monster._isAttacking = true; + + if (!_wo[22] && !_wo[27]) { + if (combat._attackMonsters[6] == -1) { + combat._attackMonsters[6] = monsterIdx; + setMonsterSprite(_indoorList[106], monster, sprites, frame, INDOOR_MONSTERS_Y[2]); + } else if (combat._attackMonsters[7] == -1) { + combat._attackMonsters[7] = monsterIdx; + setMonsterSprite(_indoorList[104], monster, sprites, frame, INDOOR_MONSTERS_Y[2]); + } else if (combat._attackMonsters[8] == -1) { + combat._attackMonsters[8] = monsterIdx; + setMonsterSprite(_indoorList[105], monster, sprites, frame, INDOOR_MONSTERS_Y[2]); + } + } + } + + if (monster._position.x == SCREEN_POSITIONING_X[dir][12] && + monster._position.y == SCREEN_POSITIONING_Y[dir][12]) { + if (_wo[27]) { + } else if (_wo[22] && _wo[23]) { + } else if (_wo[22] & _wo[20]) { + } else if (_wo[23] && _wo[17]) { + } else { + monster._isAttacking = true; + + if (combat._attackMonsters[14] == -1) { + combat._attackMonsters[14] = monsterIdx; + setMonsterSprite(_indoorList[100], monster, sprites, frame, INDOOR_MONSTERS_Y[2]); + } else if (combat._attackMonsters[20] == -1) { + combat._attackMonsters[20] = monsterIdx; + setMonsterSprite(_indoorList[101], monster, sprites, frame, INDOOR_MONSTERS_Y[2]); + } + } + } + + if (monster._position.x == SCREEN_POSITIONING_X[dir][16] && + monster._position.y == SCREEN_POSITIONING_Y[dir][16]) { + if (_wo[27]) { + } else if (_wo[22] && _wo[24]) { + } else if (_wo[22] & _wo[21]) { + } else if (_wo[24] && _wo[19]) { + } else if (_wo[21] && _wo[19]) { + } else { + monster._isAttacking = true; + + if (combat._attackMonsters[15] == -1) { + combat._attackMonsters[15] = monsterIdx; + setMonsterSprite(_indoorList[102], monster, sprites, frame, INDOOR_MONSTERS_Y[2]); + } else if (combat._attackMonsters[21] == -1) { + combat._attackMonsters[21] = monsterIdx; + setMonsterSprite(_indoorList[103], monster, sprites, frame, INDOOR_MONSTERS_Y[2]); + } + } + } + + if (monster._position.x == SCREEN_POSITIONING_X[dir][27] && + monster._position.y == SCREEN_POSITIONING_Y[dir][27]) { + if (!_wo[27] && !_wo[22] && _wo[15]) { + monster._isAttacking = true; + + if (combat._attackMonsters[9] == -1) { + combat._attackMonsters[9] = monsterIdx; + setMonsterSprite(_indoorList[70], monster, sprites, frame, INDOOR_MONSTERS_Y[3]); + } else if (combat._attackMonsters[10] == -1) { + combat._attackMonsters[10] = monsterIdx; + setMonsterSprite(_indoorList[68], monster, sprites, frame, INDOOR_MONSTERS_Y[3]); + } else if (combat._attackMonsters[11] == -1) { + combat._attackMonsters[11] = monsterIdx; + setMonsterSprite(_indoorList[69], monster, sprites, frame, INDOOR_MONSTERS_Y[3]); + } + } + } + + if (monster._position.x == SCREEN_POSITIONING_X[dir][25] && + monster._position.y == SCREEN_POSITIONING_Y[dir][25]) { + if (_wo[27] || _wo[22]) { + } else if (_wo[15] && _wo[17]) { + } else if (_wo[15] && _wo[12]) { + } else if (_wo[12] && _wo[7]) { + } else if (_wo[17] && _wo[7]) { + } else { + monster._isAttacking = true; + + if (combat._attackMonsters[16] == -1) { + combat._attackMonsters[16] = monsterIdx; + setMonsterSprite(_indoorList[62], monster, sprites, frame, INDOOR_MONSTERS_Y[3]); + } else if (combat._attackMonsters[22] == -1) { + combat._attackMonsters[22] = monsterIdx; + setMonsterSprite(_indoorList[60], monster, sprites, frame, INDOOR_MONSTERS_Y[3]); + } else if (combat._attackMonsters[24] == -1) { + combat._attackMonsters[24] = monsterIdx; + setMonsterSprite(_indoorList[61], monster, sprites, frame, INDOOR_MONSTERS_Y[3]); + } + } + } + + if (monster._position.x == SCREEN_POSITIONING_X[dir][23] && + monster._position.y == SCREEN_POSITIONING_Y[dir][23]) { + if (_wo[27]) { + } else if (_wo[22] && _wo[20]) { + } else if (_wo[22] && _wo[23]) { + } else if (_wo[20] && _wo[17]) { + } else if (_wo[23] && _wo[17]) { + } else if (_wo[12] || _wo[8]) { + } else { + monster._isAttacking = true; + + if (combat._attackMonsters[18] == -1) { + combat._attackMonsters[18] = monsterIdx; + setMonsterSprite(_indoorList[66], monster, sprites, frame, INDOOR_MONSTERS_Y[3]); + } + } + } + + if (monster._position.x == SCREEN_POSITIONING_X[dir][29] && + monster._position.y == SCREEN_POSITIONING_Y[dir][29]) { + if (_wo[27] || _wo[22]) { + } else if (_wo[15] && _wo[19]) { + } else if (_wo[15] && _wo[14]) { + } else if (_wo[14] && _wo[9]) { + } else if (_wo[19] && _wo[9]) { + } else { + monster._isAttacking = true; + + if (combat._attackMonsters[17] == -1) { + combat._attackMonsters[17] = monsterIdx; + setMonsterSprite(_indoorList[65], monster, sprites, frame, INDOOR_MONSTERS_Y[3]); + } else if (combat._attackMonsters[23] == -1) { + combat._attackMonsters[23] = monsterIdx; + setMonsterSprite(_indoorList[63], monster, sprites, frame, INDOOR_MONSTERS_Y[3]); + } else if (combat._attackMonsters[25] == -1) { + combat._attackMonsters[25] = monsterIdx; + setMonsterSprite(_indoorList[64], monster, sprites, frame, INDOOR_MONSTERS_Y[3]); + } + } + } + + if (monster._position.x == SCREEN_POSITIONING_X[dir][31] && + monster._position.y == SCREEN_POSITIONING_Y[dir][31]) { + if (_wo[27]) { + } else if (_wo[22] && _wo[21]) { + } else if (_wo[22] && _wo[24]) { + } else if (_wo[21] && _wo[19]) { + } else if (_wo[24] && _wo[19]) { + } else if (_wo[14] || _wo[10]) { + } else { + monster._isAttacking = true; + + if (combat._attackMonsters[19] == -1) { + combat._attackMonsters[19] = monsterIdx; + setMonsterSprite(_indoorList[67], monster, sprites, frame, INDOOR_MONSTERS_Y[3]); + } else if (combat._attackMonsters[23] == -1) { + combat._attackMonsters[23] = monsterIdx; + setMonsterSprite(_indoorList[63], monster, sprites, frame, INDOOR_MONSTERS_Y[3]); + } else if (combat._attackMonsters[25] == -1) { + combat._attackMonsters[25] = monsterIdx; + setMonsterSprite(_indoorList[64], monster, sprites, frame, INDOOR_MONSTERS_Y[3]); + } + } + } } } @@ -431,21 +626,20 @@ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster MonsterStruct &monsterData = _vm->_map->_monsterData[monster._spriteId]; bool flying = monsterData._flying; - _indoorList[156]._frame = frame; - _indoorList[156]._sprites = sprites; - _indoorList[156]._y = defaultY; + drawStruct._frame = frame; + drawStruct._sprites = sprites; + drawStruct._y = defaultY; if (flying) { - _indoorList[156]._x = COMBAT_FLOAT_X[_combatFloatCounter]; - _indoorList[156]._y = COMBAT_FLOAT_Y[_combatFloatCounter]; + drawStruct._x = COMBAT_FLOAT_X[_combatFloatCounter]; + drawStruct._y = COMBAT_FLOAT_Y[_combatFloatCounter]; } else { - _indoorList[156]._x = 0; + drawStruct._x = 0; } - _indoorList[156]._flags &= SPRFLAG_HORIZ_FLIPPED | SPRFLAG_4000 | SPRFLAG_2000; + drawStruct._flags &= SPRFLAG_HORIZ_FLIPPED | SPRFLAG_4000 | SPRFLAG_2000; if (monster._effect2) - _indoorList[156]._flags = MONSTER_EFFECT_FLAGS[monster._effect2][monster._effect3]; - + drawStruct._flags = MONSTER_EFFECT_FLAGS[monster._effect2][monster._effect3]; } void InterfaceMap::setIndoorObjects() { diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index c136dee534..abb2cf68f2 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -638,7 +638,7 @@ MazeMonster::MazeMonster() { _frame = 0; _id = 0; _spriteId = 0; - _field4 = 0; + _isAttacking = false; _hp = 0; _effect1 = _effect2 = 0; _effect3 = 0; diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 821922bd7f..6ac8b36973 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -250,7 +250,7 @@ struct MazeMonster { int _frame; int _id; int _spriteId; - int _field4; + bool _isAttacking; int _hp; int _effect1, _effect2; int _effect3; -- cgit v1.2.3 From d6497f78f0fe9f996be3ace6c4ef320dd58ba1c7 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 15 Jan 2015 21:50:20 -0500 Subject: XEEN: Implement setIndoorsWallPics --- engines/xeen/interface.cpp | 6 +- engines/xeen/interface_map.cpp | 229 ++++++++++++++++++++++++++++++++++++++++- engines/xeen/interface_map.h | 4 +- engines/xeen/map.cpp | 1 + engines/xeen/map.h | 1 + 5 files changed, 232 insertions(+), 9 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index eb607db7a2..7476abfa31 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -661,9 +661,9 @@ void Interface::draw3d(bool updateFlag) { } } - setIndoorsMonsters(); + setIndoorsAttackingMonsters(); setIndoorObjects(); - setIndoorWallPics(); + setIndoorsWallPics(); _indoorList[161]._sprites = nullptr; _indoorList[160]._sprites = nullptr; @@ -756,7 +756,7 @@ void Interface::startup() { animate3d(); if (_vm->_map->_isOutdoors) { - setIndoorsMonsters(); + setIndoorsAttackingMonsters(); setIndoorObjects(); } else { setOutdoorsMonsters(); diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index ba5cdbc7d0..d95868dd8a 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -374,7 +374,7 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) { _combatFloatCounter = 0; } -void InterfaceMap::setIndoorsMonsters() { +void InterfaceMap::setIndoorsAttackingMonsters() { Combat &combat = *_vm->_combat; Map &map = *_vm->_map; Direction dir = _vm->_party._mazeDirection; @@ -820,8 +820,230 @@ void InterfaceMap::setIndoorObjects() { } } -void InterfaceMap::setIndoorWallPics() { - // TODO +void InterfaceMap::setIndoorsWallPics() { + Map &map = *_vm->_map; + const Common::Point &mazePos = _vm->_party._mazePosition; + Direction dir = _vm->_party._mazeDirection; + + Common::fill(&_wp[0], &_wp[20], -1); + + for (uint idx = 0; idx < map._mobData._wallItems.size(); ++idx) { + MazeWallItem &wallItem = map._mobData._wallItems[idx]; + if (wallItem._direction != dir) + continue; + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][2]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][2])) { + if (_wp[1] == -1) { + _indoorList[148]._frame = wallItem._frame; + _indoorList[148]._sprites = wallItem._sprites; + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][7]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][7])) { + if (!_wo[27] && _wp[1] == -1) { + _indoorList[123]._frame = wallItem._frame; + _indoorList[123]._sprites = wallItem._sprites; + _wp[4] = idx; + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][5]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][5])) { + if (_wo[27] && _wo[25]) { + } else if (_wo[27] && _wo[28]) { + } else if (_wo[23] && _wo[25]) { + } else if (_wo[23] && _wo[28]) { + } else if (_wp[3] == -1) { + _indoorList[122]._frame = wallItem._frame; + _indoorList[122]._sprites = wallItem._sprites; + _wp[3] = idx; + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][9]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][9])) { + if (_wo[27] && _wo[26]) { + } else if (_wo[27] && _wo[29]) { + } else if (_wo[24] && _wo[26]) { + } else if (_wo[24] && _wo[29]) { + } else if (_wp[5] == -1) { + _indoorList[124]._frame = wallItem._frame; + _indoorList[124]._sprites = wallItem._sprites; + _wp[5] = idx; + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][14]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][14])) { + if (!_wo[22] && !_wo[27] && !_wp[8]) { + _indoorList[94]._frame = wallItem._frame; + _indoorList[94]._sprites = wallItem._sprites; + _wp[8] = idx; + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][12]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][12])) { + if (_wo[27]) { + } else if (_wo[22] && _wo[23]) { + } else if (_wo[22] && _wo[20]) { + } else if (_wo[23] && _wo[17]) { + } else if (_wo[20] && _wo[17]) { + } else if (_wp[7] == -1) { + _indoorList[93]._frame = wallItem._frame; + _indoorList[93]._sprites = wallItem._sprites; + _wp[7] = idx; + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][16]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][16])) { + if (_wo[27]) { + } else if (_wo[22] && _wo[24]) { + } else if (_wo[22] && _wo[21]) { + } else if (_wo[24] && _wo[19]) { + } else if (_wo[21] && _wo[19]) { + } else if (_wp[9] == -1) { + _indoorList[95]._frame = wallItem._frame; + _indoorList[95]._sprites = wallItem._sprites; + _wp[9] = idx; + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][12]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][12])) { + if (_wo[27]) { + } else if (_wo[25] && _wo[28]) { + } else if (_wo[20] && _wo[16]) { + } else if (_wp[6] == -1) { + _indoorList[92]._frame = wallItem._frame; + _indoorList[92]._sprites = wallItem._sprites; + _wp[6] = idx; + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][16]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][16])) { + if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[18] && _wp[10] == -1) { + _indoorList[96]._frame = wallItem._frame; + _indoorList[96]._sprites = wallItem._sprites; + _wp[10] = idx; + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][27]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][27])) { + if (!_wo[27] && !_wo[22] && !_wo[15] && _wp[15] == -1) { + _indoorList[50]._frame = wallItem._frame; + _indoorList[50]._sprites = wallItem._sprites; + _wp[15] = idx; + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][25]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][25])) { + if (_wo[27]) { + } else if (_wo[27] && _wo[22]) { + } else if (_wo[15] && _wo[17]) { + } else if (_wo[15] && _wo[12]) { + } else if (_wo[12] && _wo[7]) { + } else if (_wo[17] && _wo[7]) { + } else if (_wp[14] == -1) { + _indoorList[49]._frame = wallItem._frame; + _indoorList[49]._sprites = wallItem._sprites; + _wp[14] = idx; + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][23]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][23])) { + if (_wo[27]) { + } else if (_wo[22] && _wo[20]) { + } else if (_wo[22] && _wo[23]) { + } else if (_wo[20] && _wo[17]) { + } else if (_wo[23] && _wo[17]) { + } else if (_wo[12] && _wo[8]) { + } else if (_wp[13] == -1) { + _indoorList[48]._frame = wallItem._frame; + _indoorList[48]._sprites = wallItem._sprites; + _wp[13] = idx; + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][29]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][29])) { + if (_wo[27] || _wo[22]) { + } else if (_wo[15] && _wo[19]) { + } else if (_wo[15] && _wo[14]) { + } else if (_wo[14] && _wo[9]) { + } else if (_wo[19] && _wo[9]) { + } else if (_wp[16] == -1) { + _indoorList[51]._frame = wallItem._frame; + _indoorList[51]._sprites = wallItem._sprites; + _wp[16] = idx; + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][31]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][31])) { + if (_wo[27]) { + } else if (_wo[22] && _wo[21]) { + } else if (_wo[22] && _wo[24]) { + } else if (_wo[21] && _wo[19]) { + } else if (_wo[24] && _wo[19]) { + } else if (!_wo[14] && !_wo[10] && _wp[17] == -1) { + _indoorList[52]._frame = wallItem._frame; + _indoorList[52]._sprites = wallItem._sprites; + _wp[17] = idx; + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][23]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][23])) { + if (!_wo[27] && !_wo[20] && !_wo[12] && !_wo[23] && !_wo[8] && !_wo[30]) { + if (_wp[12] == -1) { + _indoorList[47]._frame = wallItem._frame; + _indoorList[47]._sprites = wallItem._sprites; + _wp[12] = idx; + } + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][31]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][31])) { + if (!_wo[27] && !_wo[21] && !_wo[14] && !_wo[24] && !_wo[10] && !_wo[31]) { + if (_wp[18] == -1) { + _indoorList[53]._frame = wallItem._frame; + _indoorList[53]._sprites = wallItem._sprites; + _wp[18] = idx; + } + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][23]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][23])) { + if (!_wo[25] && !_wo[28] && !_wo[20] && !_wo[11] && !_wo[16] && !_wo[30] && !_wo[32]) { + if (_wp[11] == -1) { + _indoorList[46]._frame = wallItem._frame; + _indoorList[46]._sprites = wallItem._sprites; + _wp[11] = idx; + } + } + } + + if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][31]) && + mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][31])) { + if (!_wo[26] && !_wo[20] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31] && !_wo[33]) { + if (_wp[19] == -1) { + _indoorList[54]._frame = wallItem._frame; + _indoorList[54]._sprites = wallItem._sprites; + _wp[19] = idx; + } + } + } + } } void InterfaceMap::setOutdoorsMonsters() { @@ -835,7 +1057,6 @@ void InterfaceMap::setOutdoorsObjects() { void InterfaceMap::drawIndoors() { Map &map = *_vm->_map; int surfaceId; - int idx; for (int cellIndex = 0; cellIndex < 25; ++cellIndex) { map.getCell(DRAW_NUMBERS[cellIndex]); diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index ea40c30a79..ae9abd2e5e 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -105,11 +105,11 @@ public: public: InterfaceMap(XeenEngine *vm); - void setIndoorsMonsters(); + void setIndoorsAttackingMonsters(); void setIndoorObjects(); - void setIndoorWallPics(); + void setIndoorsWallPics(); void drawIndoors(); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index abb2cf68f2..a5a40c9029 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -650,6 +650,7 @@ MazeMonster::MazeMonster() { MazeWallItem::MazeWallItem() { _id = 0; + _frame = 0; _spriteId = 0; _direction = DIR_NORTH; _sprites = nullptr; diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 6ac8b36973..8e6fee2811 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -264,6 +264,7 @@ class MazeWallItem { public: Common::Point _position; int _id; + int _frame; int _spriteId; Direction _direction; SpriteResource *_sprites; -- cgit v1.2.3 From 0ceefedce5ed33f545db9ab00b881d72ddd52186 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 15 Jan 2015 23:20:33 -0500 Subject: XEEN: Fix frame calculations for low part of _indoorList --- engines/xeen/interface_map.cpp | 6 +++--- engines/xeen/resources.cpp | 14 ++++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index d95868dd8a..3d9ed10c5e 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -1066,12 +1066,12 @@ void InterfaceMap::drawIndoors() { drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId]; surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; - if (surfaceId == 5 || surfaceId == 12) { - drawStruct._flags = _flipWtr; + if (surfaceId == 0 || surfaceId == 5 || surfaceId == 12) { + drawStruct._flags = _flipWtr ? 1 : 0; drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWtr ? 1 : 0]; } else { drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWall ? 1 : 0]; - drawStruct._flags = _flipWall ? 0 : SPRFLAG_HORIZ_FLIPPED; + drawStruct._flags = _flipWall ? SPRFLAG_HORIZ_FLIPPED : 0; } } diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 87540b8df4..21a967dbf1 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -433,15 +433,17 @@ const byte WALL_NUMBERS[4][96] = { }; const int DRAW_NUMBERS[25] = { - 36, 37, 38, 43, 42, 41, 39, 20, 22, 24, 33, 31, 29, 26, 10, 11, - 18, 16, 13, 5, 9, 6, 0, 4, 1 + 36, 37, 38, 43, 42, 41, + 39, 20, 22, 24, 33, 31, + 29, 26, 10, 11, 18, 16, + 13, 5, 9, 6, 0, 4, 1 }; const int DRAW_FRAMES[25][2] = { - { 18, 24 }, { 19, 23 }, { 20, 22 }, { 10, 24 }, { 19, 23 }, { 20, 22 }, - { 21, 21 }, { 11, 17 }, { 12, 16 }, { 13, 15 }, { 11, 17 }, { 12, 16 }, - { 13, 15 }, { 14, 14 }, { 6, 10 }, { 7, 9 }, { 6, 10 }, { 7, 9 }, - { 8, 8 }, { 3, 5 }, { 3, 5 }, { 4, 4 }, { 0, 2 }, { 0, 2 }, + { 18, 24 }, { 19, 23 }, { 20, 22 }, { 24, 18 }, { 23, 19 }, { 22, 20 }, + { 21, 21 }, { 11, 17 }, { 12, 16 }, { 13, 15 }, { 17, 11 }, { 16, 12 }, + { 15, 13 }, { 14, 14 }, { 6, 10 }, { 7, 9 }, { 10, 6 }, { 9, 7 }, + { 8, 8 }, { 3, 5 }, { 5, 3 }, { 4, 4 }, { 0, 2 }, { 2, 0 }, { 1, 1 } }; -- cgit v1.2.3 From b83b63b0cf161fa27352cb40fb19d8169b882b0f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 15 Jan 2015 23:37:52 -0500 Subject: XEEN: Fix _wp switch statements --- engines/xeen/interface.cpp | 48 ++++++++++++++++++++++---------------------- engines/xeen/interface_map.h | 2 +- 2 files changed, 25 insertions(+), 25 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 7476abfa31..72bcdd95d1 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -862,7 +862,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(1)) { + switch (_vm->_map->getCell(1) - 1) { case 1: ++_wo[72]; break; @@ -932,7 +932,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(3)) { + switch (_vm->_map->getCell(3) - 1) { case 1: ++_wo[73]; break; @@ -1044,7 +1044,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(6)) { + switch (_vm->_map->getCell(6) - 1) { case 1: ++_wo[67]; break; @@ -1116,7 +1116,7 @@ void Interface::setMazeBits() { _thinWall = (_vm->_map->_currentWall._data != 0x8888) && _wo[27]; - switch (_vm->_map->getCell(8)) { + switch (_vm->_map->getCell(8) - 1) { case 1: ++_wo[68]; break; @@ -1231,7 +1231,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(11)) { + switch (_vm->_map->getCell(11) - 1) { case 1: ++_wo[60]; break; @@ -1301,7 +1301,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(13)) { + switch (_vm->_map->getCell(13) - 1) { case 1: ++_wo[61]; break; @@ -1371,7 +1371,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(15)) { + switch (_vm->_map->getCell(15) - 1) { case 1: ++_wo[63]; break; @@ -1441,7 +1441,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(17)) { + switch (_vm->_map->getCell(17) - 1) { case 1: ++_wo[62]; break; @@ -1556,7 +1556,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(20)) { + switch (_vm->_map->getCell(20) - 1) { case 1: ++_wo[76]; break; @@ -1626,7 +1626,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(22)) { + switch (_vm->_map->getCell(22) - 1) { case 1: ++_wo[74]; break; @@ -1696,7 +1696,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(24)) { + switch (_vm->_map->getCell(24) - 1) { case 1: ++_wo[52]; break; @@ -1766,7 +1766,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(26)) { + switch (_vm->_map->getCell(26) - 1) { case 1: ++_wo[51]; break; @@ -1836,7 +1836,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(28)) { + switch (_vm->_map->getCell(28) - 1) { case 1: ++_wo[53]; break; @@ -1906,7 +1906,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(30)) { + switch (_vm->_map->getCell(30) - 1) { case 1: ++_wo[54]; break; @@ -1975,7 +1975,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(32)) { + switch (_vm->_map->getCell(32) - 1) { case 1: ++_wo[75]; break; @@ -2045,7 +2045,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(34)) { + switch (_vm->_map->getCell(34) - 1) { case 1: ++_wo[77]; break; @@ -2115,7 +2115,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(36)) { + switch (_vm->_map->getCell(36) - 1) { case 1: ++_wo[83]; break; @@ -2139,7 +2139,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(37)) { + switch (_vm->_map->getCell(37) - 1) { case 1: ++_wo[82]; break; @@ -2163,7 +2163,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(38)) { + switch (_vm->_map->getCell(38) - 1) { case 1: ++_wo[81]; break; @@ -2187,7 +2187,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(34)) { + switch (_vm->_map->getCell(34) - 1) { case 1: ++_wo[80]; break; @@ -2211,7 +2211,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(40)) { + switch (_vm->_map->getCell(40) - 1) { case 1: ++_wo[84]; break; @@ -2235,7 +2235,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(41)) { + switch (_vm->_map->getCell(41) - 1) { case 1: ++_wo[85]; break; @@ -2259,7 +2259,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(42)) { + switch (_vm->_map->getCell(42) - 1) { case 1: ++_wo[86]; break; @@ -2283,7 +2283,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(43)) { + switch (_vm->_map->getCell(43) - 1) { case 1: ++_wo[87]; break; diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index ae9abd2e5e..e9f32bd587 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -89,7 +89,7 @@ private: void setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, SpriteResource *sprites, int frame, int defaultY); protected: - byte _wp[20]; + int8 _wp[20]; byte _wo[308]; int _overallFrame; bool _flipWtr; -- cgit v1.2.3 From 484901e7a299f26afa1be9ca1644fee0aef7acf1 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 16 Jan 2015 08:30:27 -0500 Subject: XEEN: Fixes and cleanup for setIndoorsObjects --- engines/xeen/interface.cpp | 10 +- engines/xeen/interface_map.cpp | 267 ++++++++++++++++++++++++----------------- engines/xeen/interface_map.h | 28 ++--- 3 files changed, 176 insertions(+), 129 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 72bcdd95d1..9aa76f614e 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -560,8 +560,8 @@ void Interface::draw3d(bool updateFlag) { // Loop to update the frame numbers for each maze object, applying the animation frame // limits as specified by the map's _animationInfo listing - for (uint i = 0; i < map._mobData._objects.size(); ++i) { - MazeObject &mazeObject = map._mobData._objects[i]; + for (uint idx = 0; idx < map._mobData._objects.size(); ++idx) { + MazeObject &mazeObject = map._mobData._objects[idx]; AnimationEntry &animEntry = map._animationInfo[mazeObject._spriteId]; int directionIndex = DIRECTION_ANIM_POSITIONS[mazeObject._direction][partyDirection]; @@ -569,13 +569,13 @@ void Interface::draw3d(bool updateFlag) { mazeObject._frame = animEntry._frame1._frames[directionIndex]; } else { ++mazeObject._frame; - if ((int)i == objNum && _animCounter > 0 && ( + if ((int)idx == objNum && _animCounter > 0 && ( objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) || objObject._spriteId == 58 || objObject._spriteId == 73)) { if (mazeObject._frame > 4 || mazeObject._spriteId == 58) mazeObject._frame = 1; - } else if (mazeObject._frame == animEntry._frame2._frames[directionIndex]) { - mazeObject._frame = animEntry._frame2._frames[directionIndex]; + } else if (mazeObject._frame >= animEntry._frame2._frames[directionIndex]) { + mazeObject._frame = animEntry._frame1._frames[directionIndex]; } } diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 3d9ed10c5e..da9c2957c9 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -644,9 +644,9 @@ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster void InterfaceMap::setIndoorObjects() { Common::Point mazePos = _vm->_party._mazePosition; - _objNumber = 0; - const int8 *posOffset = &SCREEN_POSITIONING_X[_vm->_party._mazeDirection][0]; + Direction dir = _vm->_party._mazeDirection; Common::Point pt; + _objNumber = 0; Common::Array<MazeObject> &objects = _vm->_map->_mobData._objects; for (uint idx = 0; idx < objects.size(); ++idx) { @@ -656,14 +656,14 @@ void InterfaceMap::setIndoorObjects() { int listOffset; if (_vm->_files->_isDarkCc) { listOffset = mazeObject._spriteId == 47 ? 1 : 0; - } - else { + } else { listOffset = mazeObject._spriteId == 113 ? 1 : 0; } // Position 1 - pt = Common::Point(mazePos.x + posOffset[2], mazePos.y + posOffset[194]); - if (pt == mazeObject._position && _indoorList._objects0._frame == -1) { + if ((mazePos.x + SCREEN_POSITIONING_X[dir][2]) == mazeObject._position.x + && (mazePos.y + SCREEN_POSITIONING_Y[dir][2]) == mazeObject._position.y + && _indoorList._objects0._frame == -1) { _indoorList._objects0._x = INDOOR_OBJECT_X[listOffset][0]; _indoorList._objects0._y = INDOOR_OBJECT_Y[listOffset][0]; _indoorList._objects0._frame = mazeObject._frame; @@ -675,8 +675,9 @@ void InterfaceMap::setIndoorObjects() { } // Position 2 - pt = Common::Point(mazePos.x + posOffset[7], mazePos.y + posOffset[199]); - if (pt == mazeObject._position && !_wo[27] && _indoorList._objects1._frame == -1) { + if ((mazePos.x + SCREEN_POSITIONING_X[dir][7]) == mazeObject._position.x + && (mazePos.y + SCREEN_POSITIONING_Y[dir][7]) == mazeObject._position.y + && !_wo[27] && _indoorList._objects1._frame == -1) { _indoorList._objects1._x = INDOOR_OBJECT_X[listOffset][1]; _indoorList._objects1._y = INDOOR_OBJECT_Y[listOffset][1]; _indoorList._objects1._frame = mazeObject._frame; @@ -687,135 +688,181 @@ void InterfaceMap::setIndoorObjects() { } // Position 3 - pt = Common::Point(mazePos.x + posOffset[5], mazePos.y + posOffset[197]); - if (pt == mazeObject._position && (!_wo[27] || !_wo[25]) && (!_wo[27] || !_wo[28]) && - (!_wo[23] || !_wo[25]) && (!_wo[23] || !_wo[28]) && - _indoorList._objects2._frame == -1) { - _indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][2]; - _indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][2]; - _indoorList._objects2._frame = mazeObject._frame; - _indoorList._objects2._sprites = mazeObject._sprites; - _indoorList._objects2._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects2._flags |= SPRFLAG_HORIZ_FLIPPED; + if ((mazePos.x + SCREEN_POSITIONING_X[dir][5]) == mazeObject._position.x + && (mazePos.y + SCREEN_POSITIONING_Y[dir][5]) == mazeObject._position.y) { + if (_wo[27] && _wo[25]) { + } else if (_wo[27] && _wo[28]) { + } else if (_wo[23] && _wo[25]) { + } else if (_wo[23] && _wo[28]) { + } else if (_indoorList._objects2._frame == -1) { + _indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][2]; + _indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][2]; + _indoorList._objects2._frame = mazeObject._frame; + _indoorList._objects2._sprites = mazeObject._sprites; + _indoorList._objects2._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects2._flags |= SPRFLAG_HORIZ_FLIPPED; + } } // Position 4 - pt = Common::Point(mazePos.x + posOffset[9], mazePos.y + posOffset[201]); - if (pt == mazeObject._position && (!_wo[27] || !_wo[26]) && (!_wo[27] || !_wo[29]) && - (!_wo[24] || !_wo[26]) && (!_wo[24] || !_wo[29]) && _indoorList._objects3._frame == -1) { - _indoorList._objects3._x = INDOOR_OBJECT_X[listOffset][3]; - _indoorList._objects3._y = INDOOR_OBJECT_Y[listOffset][3]; - _indoorList._objects3._frame = mazeObject._frame; - _indoorList._objects3._sprites = mazeObject._sprites; - _indoorList._objects3._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects3._flags |= SPRFLAG_HORIZ_FLIPPED; + if ((mazePos.x + SCREEN_POSITIONING_X[dir][9]) == mazeObject._position.x + && (mazePos.y + SCREEN_POSITIONING_Y[dir][9]) == mazeObject._position.y) { + if (_wo[27] && _wo[26]) { + } else if (_wo[27] && _wo[29]) { + } else if (_wo[24] && _wo[26]) { + } else if (_wo[24] && _wo[29]) { + } else if (_indoorList._objects3._frame == -1) { + _indoorList._objects3._x = INDOOR_OBJECT_X[listOffset][3]; + _indoorList._objects3._y = INDOOR_OBJECT_Y[listOffset][3]; + _indoorList._objects3._frame = mazeObject._frame; + _indoorList._objects3._sprites = mazeObject._sprites; + _indoorList._objects3._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects3._flags |= SPRFLAG_HORIZ_FLIPPED; + } } // Position 5 - pt = Common::Point(mazePos.x + posOffset[14], mazePos.y + posOffset[206]); - if (pt == mazeObject._position && !_wo[22] && !_wo[27] && _indoorList._objects4._frame == -1) { - _indoorList._objects4._x = INDOOR_OBJECT_X[listOffset][4]; - _indoorList._objects4._y = INDOOR_OBJECT_Y[listOffset][4]; - _indoorList._objects4._frame = mazeObject._frame; - _indoorList._objects4._sprites = mazeObject._sprites; - _indoorList._objects4._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects4._flags |= SPRFLAG_HORIZ_FLIPPED; + if ((mazePos.x + SCREEN_POSITIONING_X[dir][14]) == mazeObject._position.x + && (mazePos.y + SCREEN_POSITIONING_Y[dir][14]) == mazeObject._position.y) { + if (!_wo[22] && !_wo[27] && _indoorList._objects4._frame == -1) { + _indoorList._objects4._x = INDOOR_OBJECT_X[listOffset][4]; + _indoorList._objects4._y = INDOOR_OBJECT_Y[listOffset][4]; + _indoorList._objects4._frame = mazeObject._frame; + _indoorList._objects4._sprites = mazeObject._sprites; + _indoorList._objects4._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects4._flags |= SPRFLAG_HORIZ_FLIPPED; + } } // Position 6 - pt = Common::Point(mazePos.x + posOffset[12], mazePos.y + posOffset[204]); - if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[23]) && (!_wo[22] || !_wo[20]) && - (!_wo[23] || !_wo[17]) && (!_wo[20] || !_wo[17]) && _indoorList._objects5._frame == -1) { - _indoorList._objects5._x = INDOOR_OBJECT_X[listOffset][5]; - _indoorList._objects5._y = INDOOR_OBJECT_Y[listOffset][5]; - _indoorList._objects5._frame = mazeObject._frame; - _indoorList._objects5._sprites = mazeObject._sprites; - _indoorList._objects5._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects5._flags |= SPRFLAG_HORIZ_FLIPPED; + if ((mazePos.x + SCREEN_POSITIONING_X[dir][12]) == mazeObject._position.x + && (mazePos.y + SCREEN_POSITIONING_Y[dir][12]) == mazeObject._position.y) { + if (_wo[27]) { + } else if (_wo[22] && _wo[23]) { + } else if (_wo[22] && _wo[20]) { + } else if (_wo[23] && _wo[17]) { + } else if (_wo[20] && _wo[17]) { + } else if (_indoorList._objects5._frame == -1) { + _indoorList._objects5._x = INDOOR_OBJECT_X[listOffset][5]; + _indoorList._objects5._y = INDOOR_OBJECT_Y[listOffset][5]; + _indoorList._objects5._frame = mazeObject._frame; + _indoorList._objects5._sprites = mazeObject._sprites; + _indoorList._objects5._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects5._flags |= SPRFLAG_HORIZ_FLIPPED; + } } // Position 7 - pt = Common::Point(mazePos.x + posOffset[16], mazePos.y + posOffset[208]); - if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[24]) && (!_wo[22] || !_wo[21]) && - (!_wo[24] || !_wo[19]) && (!_wo[21] || !_wo[19]) && _indoorList._objects6._frame == -1) { - _indoorList._objects6._x = INDOOR_OBJECT_X[listOffset][6]; - _indoorList._objects6._y = INDOOR_OBJECT_Y[listOffset][6]; - _indoorList._objects6._frame = mazeObject._frame; - _indoorList._objects6._sprites = mazeObject._sprites; - _indoorList._objects6._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects6._flags |= SPRFLAG_HORIZ_FLIPPED; + if ((mazePos.x + SCREEN_POSITIONING_X[dir][16]) == mazeObject._position.x + && (mazePos.y + SCREEN_POSITIONING_Y[dir][16]) == mazeObject._position.y) { + if (_wo[27]) { + } else if (_wo[22] && _wo[24]) { + } else if (_wo[22] && _wo[21]) { + } else if (_wo[24] && _wo[19]) { + } else if (_wo[21] && _wo[19]) { + } else if (_indoorList._objects6._frame == -1) { + _indoorList._objects6._x = INDOOR_OBJECT_X[listOffset][6]; + _indoorList._objects6._y = INDOOR_OBJECT_Y[listOffset][6]; + _indoorList._objects6._frame = mazeObject._frame; + _indoorList._objects6._sprites = mazeObject._sprites; + _indoorList._objects6._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects6._flags |= SPRFLAG_HORIZ_FLIPPED; + } } // Position 8 - pt = Common::Point(mazePos.x + posOffset[27], mazePos.y + posOffset[219]); - if (pt == mazeObject._position && !_wo[27] && !_wo[22] && !_wo[15] && _indoorList._objects7._frame == -1) { - _indoorList._objects7._x = INDOOR_OBJECT_X[listOffset][7]; - _indoorList._objects7._y = INDOOR_OBJECT_Y[listOffset][7]; - _indoorList._objects7._frame = mazeObject._frame; - _indoorList._objects7._sprites = mazeObject._sprites; - _indoorList._objects7._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects7._flags |= SPRFLAG_HORIZ_FLIPPED; + if ((mazePos.x + SCREEN_POSITIONING_X[dir][27]) == mazeObject._position.x + && (mazePos.y + SCREEN_POSITIONING_Y[dir][27]) == mazeObject._position.y) { + if (!_wo[27] && !_wo[22] && !_wo[15] && _indoorList._objects7._frame == -1) { + _indoorList._objects7._x = INDOOR_OBJECT_X[listOffset][7]; + _indoorList._objects7._y = INDOOR_OBJECT_Y[listOffset][7]; + _indoorList._objects7._frame = mazeObject._frame; + _indoorList._objects7._sprites = mazeObject._sprites; + _indoorList._objects7._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects7._flags |= SPRFLAG_HORIZ_FLIPPED; + } } // Position 9 - pt = Common::Point(mazePos.x + posOffset[25], mazePos.y + posOffset[217]); - if (pt == mazeObject._position && !_wo[27] && (!_wo[15] || !_wo[17]) && (!_wo[15] || !_wo[12]) && - (!_wo[12] || !_wo[7]) && (!_wo[17] || !_wo[7]) && _indoorList._objects5._frame == -1) { - _indoorList._objects8._x = INDOOR_OBJECT_X[listOffset][8]; - _indoorList._objects8._y = INDOOR_OBJECT_Y[listOffset][8]; - _indoorList._objects8._frame = mazeObject._frame; - _indoorList._objects8._sprites = mazeObject._sprites; - _indoorList._objects8._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects8._flags |= SPRFLAG_HORIZ_FLIPPED; + if ((mazePos.x + SCREEN_POSITIONING_X[dir][25]) == mazeObject._position.x + && (mazePos.y + SCREEN_POSITIONING_Y[dir][25]) == mazeObject._position.y) { + if (_wo[27] || _wo[22]) { + } else if (_wo[15] && _wo[17]) { + } else if (_wo[15] && _wo[12]) { + } else if (_wo[12] && _wo[7]) { + } else if (_wo[17] && _wo[7]) { + } else if (_indoorList._objects8._frame == -1) { + _indoorList._objects8._x = INDOOR_OBJECT_X[listOffset][8]; + _indoorList._objects8._y = INDOOR_OBJECT_Y[listOffset][8]; + _indoorList._objects8._frame = mazeObject._frame; + _indoorList._objects8._sprites = mazeObject._sprites; + _indoorList._objects8._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects8._flags |= SPRFLAG_HORIZ_FLIPPED; + } } // Position 10 - pt = Common::Point(mazePos.x + posOffset[23], mazePos.y + posOffset[215]); - if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[20]) && (!_wo[22] || !_wo[23]) && - (!_wo[20] || !_wo[17]) && (!_wo[23] || !_wo[17]) && !_wo[12] && !_wo[8] && - _indoorList._objects9._frame == -1) { - _indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][9]; - _indoorList._objects9._y = INDOOR_OBJECT_Y[listOffset][9]; - _indoorList._objects9._frame = mazeObject._frame; - _indoorList._objects9._sprites = mazeObject._sprites; - _indoorList._objects9._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects9._flags |= SPRFLAG_HORIZ_FLIPPED; + if ((mazePos.x + SCREEN_POSITIONING_X[dir][23]) == mazeObject._position.x + && (mazePos.y + SCREEN_POSITIONING_Y[dir][23]) == mazeObject._position.y) { + if (_wo[27]) { + } else if (_wo[22] && _wo[20]) { + } else if (_wo[22] && _wo[23]) { + } else if (_wo[20] && _wo[17]) { + } else if (_wo[23] && _wo[17]) { + } else if (!_wo[12] && !_wo[8] && _indoorList._objects9._frame == -1) { + _indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][9]; + _indoorList._objects9._y = INDOOR_OBJECT_Y[listOffset][9]; + _indoorList._objects9._frame = mazeObject._frame; + _indoorList._objects9._sprites = mazeObject._sprites; + _indoorList._objects9._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects9._flags |= SPRFLAG_HORIZ_FLIPPED; + } } // Block 11 - pt = Common::Point(mazePos.x + posOffset[29], mazePos.y + posOffset[221]); - if (pt == mazeObject._position && !_wo[27] && !_wo[22] && (!_wo[15] || !_wo[19]) && - (!_wo[15] || !_wo[14]) && (!_wo[14] || !_wo[9]) && (!_wo[19] || !_wo[9]) && - _indoorList._objects10._frame == -1) { - _indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][10]; - _indoorList._objects10._y = INDOOR_OBJECT_Y[listOffset][10]; - _indoorList._objects10._frame = mazeObject._frame; - _indoorList._objects10._sprites = mazeObject._sprites; - _indoorList._objects10._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects10._flags |= SPRFLAG_HORIZ_FLIPPED; + if ((mazePos.x + SCREEN_POSITIONING_X[dir][29]) == mazeObject._position.x + && (mazePos.y + SCREEN_POSITIONING_Y[dir][29]) == mazeObject._position.y) { + if (_wo[27]) { + } else if (_wo[15] && _wo[19]) { + } else if (_wo[15] && _wo[14]) { + } else if (_wo[14] && _wo[9]) { + } else if (_wo[19] && _wo[9]) { + } else if (_indoorList._objects10._frame == -1) { + _indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][10]; + _indoorList._objects10._y = INDOOR_OBJECT_Y[listOffset][10]; + _indoorList._objects10._frame = mazeObject._frame; + _indoorList._objects10._sprites = mazeObject._sprites; + _indoorList._objects10._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects10._flags |= SPRFLAG_HORIZ_FLIPPED; + } } // Block 12 - pt = Common::Point(mazePos.x + posOffset[31], mazePos.y + posOffset[223]); - if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[21]) && (!_wo[22] || !_wo[24]) && - (!_wo[21] || !_wo[19]) && (!_wo[24] || !_wo[19]) && !_wo[14] && !_wo[10] && - _indoorList._objects11._frame == -1) { - _indoorList._objects11._x = INDOOR_OBJECT_X[listOffset][11]; - _indoorList._objects11._y = INDOOR_OBJECT_Y[listOffset][11]; - _indoorList._objects11._frame = mazeObject._frame; - _indoorList._objects11._sprites = mazeObject._sprites; - _indoorList._objects11._flags &= ~SPRFLAG_HORIZ_FLIPPED; - if (mazeObject._flipped) - _indoorList._objects11._flags |= SPRFLAG_HORIZ_FLIPPED; + if ((mazePos.x + SCREEN_POSITIONING_X[dir][31]) == mazeObject._position.x + && (mazePos.y + SCREEN_POSITIONING_Y[dir][31]) == mazeObject._position.y) { + if (_wo[27]) { + } else if (_wo[22] && _wo[21]) { + } else if (_wo[22] && _wo[24]) { + } else if (_wo[21] && _wo[19]) { + } else if (_wo[24] && _wo[19]) { + } else if (!_wo[14] && !_wo[10] && !_indoorList._objects11._frame == -1) { + _indoorList._objects11._x = INDOOR_OBJECT_X[listOffset][11]; + _indoorList._objects11._y = INDOOR_OBJECT_Y[listOffset][11]; + _indoorList._objects11._frame = mazeObject._frame; + _indoorList._objects11._sprites = mazeObject._sprites; + _indoorList._objects11._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (mazeObject._flipped) + _indoorList._objects11._flags |= SPRFLAG_HORIZ_FLIPPED; + } } } } diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index e9f32bd587..8013228122 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -53,20 +53,20 @@ public: DrawStruct &_sky; DrawStruct &_ground; DrawStruct &_horizon; - DrawStruct &_swl_0F1R, _swl_0F1L, _swl_1F1R, _swl_1F1L, - _swl_2F2R, _swl_2F1R, _swl_2F1L, _swl_2F2L, - _swl_3F1R, _swl_3F2R, _swl_3F3R, _swl_3F4R, - _swl_3F1L, _swl_3F2L, _swl_3F3L, _swl_3F4L, - _swl_4F4R, _swl_4F3R, _swl_4F2R, _swl_4F1R, - _swl_4F1L, _swl_4F2L, _swl_4F3L, _swl_4F4L; - DrawStruct &_fwl_4F4R, _fwl_4F3R, _fwl_4F2R, _fwl_4F1R, - _fwl_4F, _fwl_4F1L, _fwl_4F2L, _fwl_4F3L, _fwl_4F4L; - DrawStruct &_fwl_2F1R, _fwl_2F, _fwl_2F1L, _fwl_3F2R, - _fwl_3F1R, _fwl_3F, _fwl_3F1L, _fwl_3F2L; - DrawStruct &_fwl_1F, _fwl_1F1R, _fwl_1F1L; - DrawStruct &_objects0, _objects1, _objects2, _objects3; - DrawStruct &_objects4, _objects5, _objects6, _objects7; - DrawStruct &_objects8, _objects9, _objects10, _objects11; + DrawStruct &_swl_0F1R, &_swl_0F1L, &_swl_1F1R, &_swl_1F1L, + &_swl_2F2R, &_swl_2F1R, &_swl_2F1L, &_swl_2F2L, + &_swl_3F1R, &_swl_3F2R, &_swl_3F3R, &_swl_3F4R, + &_swl_3F1L, &_swl_3F2L, &_swl_3F3L, &_swl_3F4L, + &_swl_4F4R, &_swl_4F3R, &_swl_4F2R, &_swl_4F1R, + &_swl_4F1L, &_swl_4F2L, &_swl_4F3L, &_swl_4F4L; + DrawStruct &_fwl_4F4R, &_fwl_4F3R, &_fwl_4F2R, &_fwl_4F1R, + &_fwl_4F, &_fwl_4F1L, &_fwl_4F2L, &_fwl_4F3L, &_fwl_4F4L; + DrawStruct &_fwl_2F1R, &_fwl_2F, &_fwl_2F1L, &_fwl_3F2R, + &_fwl_3F1R, &_fwl_3F, &_fwl_3F1L, &_fwl_3F2L; + DrawStruct &_fwl_1F, &_fwl_1F1R, &_fwl_1F1L; + DrawStruct &_objects0, &_objects1, &_objects2, &_objects3; + DrawStruct &_objects4, &_objects5, &_objects6, &_objects7; + DrawStruct &_objects8, &_objects9, &_objects10, &_objects11; public: IndoorDrawList(); -- cgit v1.2.3 From 6bfd599535b839ce51261ff7ed82bbca92538050 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 16 Jan 2015 21:26:06 -0500 Subject: XEEN: Fixes for map loading cells and indoor sprite list references --- engines/xeen/interface.cpp | 44 +++++++++++++++++------------------ engines/xeen/interface_map.cpp | 53 +++++++++++++++++++++--------------------- engines/xeen/interface_map.h | 2 +- engines/xeen/map.cpp | 10 ++++---- 4 files changed, 55 insertions(+), 54 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 9aa76f614e..f3060c2cf4 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -662,7 +662,7 @@ void Interface::draw3d(bool updateFlag) { } setIndoorsAttackingMonsters(); - setIndoorObjects(); + setIndoorsObjects(); setIndoorsWallPics(); _indoorList[161]._sprites = nullptr; @@ -757,7 +757,7 @@ void Interface::startup() { animate3d(); if (_vm->_map->_isOutdoors) { setIndoorsAttackingMonsters(); - setIndoorObjects(); + setIndoorsObjects(); } else { setOutdoorsMonsters(); setOutdoorsObjects(); @@ -816,7 +816,7 @@ void Interface::setMainButtons() { void Interface::setMazeBits() { Common::fill(&_wo[0], &_wo[308], 0); - switch (_vm->_map->getCell(0)) { + switch (_vm->_map->getCell(0) - 1) { case 0: ++_wo[125]; break; @@ -886,7 +886,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(2)) { + switch (_vm->_map->getCell(2) - 1) { case 0: ++_wo[127]; break; @@ -956,7 +956,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(4)) { + switch (_vm->_map->getCell(4) - 1) { case 0: ++_wo[126]; break; @@ -1002,7 +1002,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(5)) { + switch (_vm->_map->getCell(5) - 1) { case 0: ++_wo[122]; break; @@ -1068,7 +1068,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(7)) { + switch (_vm->_map->getCell(7) - 1) { case 0: ++_wo[124]; break; @@ -1140,7 +1140,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(9)) { + switch (_vm->_map->getCell(9) - 1) { case 0: ++_wo[123]; break; @@ -1186,7 +1186,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(10)) { + switch (_vm->_map->getCell(10) - 1) { case 0: ++_wo[117]; break; @@ -1255,7 +1255,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(12)) { + switch (_vm->_map->getCell(12) - 1) { case 0: ++_wo[118]; break; @@ -1325,7 +1325,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(14)) { + switch (_vm->_map->getCell(14) - 1) { case 0: ++_wo[121]; break; @@ -1395,7 +1395,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(16)) { + switch (_vm->_map->getCell(16) - 1) { case 0: ++_wo[120]; break; @@ -1465,7 +1465,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(18)) { + switch (_vm->_map->getCell(18) - 1) { case 0: ++_wo[119]; break; @@ -1511,7 +1511,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(19)) { + switch (_vm->_map->getCell(19) - 1) { case 0: ++_wo[108]; break; @@ -1580,7 +1580,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(21)) { + switch (_vm->_map->getCell(21) - 1) { case 0: ++_wo[109]; break; @@ -1650,7 +1650,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(23)) { + switch (_vm->_map->getCell(23) - 1) { case 0: ++_wo[110]; break; @@ -1720,7 +1720,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(25)) { + switch (_vm->_map->getCell(25) - 1) { case 0: ++_wo[111]; break; @@ -1790,7 +1790,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(27)) { + switch (_vm->_map->getCell(27) - 1) { case 0: ++_wo[116]; break; @@ -1860,7 +1860,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(29)) { + switch (_vm->_map->getCell(29) - 1) { case 0: ++_wo[115]; break; @@ -1930,7 +1930,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(31)) { + switch (_vm->_map->getCell(31) - 1) { case 0: ++_wo[114]; break; @@ -1999,7 +1999,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(33)) { + switch (_vm->_map->getCell(33) - 1) { case 0: ++_wo[112]; break; @@ -2069,7 +2069,7 @@ void Interface::setMazeBits() { break; } - switch (_vm->_map->getCell(35)) { + switch (_vm->_map->getCell(35) - 1) { case 0: ++_wo[113]; break; diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index da9c2957c9..6780a5c2ee 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -166,7 +166,7 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2 IndoorDrawList::IndoorDrawList() : _sky(_data[1]), _ground(_data[2]), _horizon(_data[28]), - _swl_0F1R(_data[ 46]), _swl_0F1L(_data[44]), _swl_1F1R(_data[134]), + _swl_0F1R(_data[146]), _swl_0F1L(_data[144]), _swl_1F1R(_data[134]), _swl_1F1L(_data[133]), _swl_2F2R(_data[110]), _swl_2F1R(_data[109]), _swl_2F1L(_data[108]), _swl_2F2L(_data[107]), _swl_3F1R(_data[ 78]), _swl_3F2R(_data[ 77]), _swl_3F3R(_data[ 76]), _swl_3F4R(_data[ 75]), @@ -377,6 +377,7 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) { void InterfaceMap::setIndoorsAttackingMonsters() { Combat &combat = *_vm->_combat; Map &map = *_vm->_map; + Common::Point mazePos = _vm->_party._mazePosition; Direction dir = _vm->_party._mazeDirection; const int INDOOR_MONSTERS_Y[4] = { 2, 34, 53, 59 }; @@ -392,8 +393,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } // The following long sequence sets up monsters in the various positions - if (monster._position.x == SCREEN_POSITIONING_X[dir][2] && - monster._position.y == SCREEN_POSITIONING_Y[dir][2]) { + if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][2]) && + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][2])) { monster._isAttacking = true; if (combat._attackMonsters[0] == -1) { combat._attackMonsters[0] = monsterIdx; @@ -407,8 +408,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } } - if (monster._position.x == SCREEN_POSITIONING_X[dir][7] && - monster._position.y == SCREEN_POSITIONING_Y[dir][7]) { + if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][7]) && + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][7])) { monster._isAttacking = true; if (!_wo[27]) { if (combat._attackMonsters[3] == -1) { @@ -424,8 +425,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } } - if (monster._position.x == SCREEN_POSITIONING_X[dir][5] && - monster._position.y == SCREEN_POSITIONING_Y[dir][5]) { + if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][5]) && + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][5])) { if (_wo[27] && _wo[25]) { } else if (_wo[27] && _wo[28]) { } else if (_wo[23] & _wo[25]) { @@ -440,8 +441,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } } - if (monster._position.x == SCREEN_POSITIONING_X[dir][9] && - monster._position.y == SCREEN_POSITIONING_Y[dir][9]) { + if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][9]) && + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][9])) { if (_wo[27] && _wo[26]) { } else if (_wo[27] && _wo[29]) { } else if (_wo[24] & _wo[26]) { @@ -456,8 +457,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } } - if (monster._position.x == SCREEN_POSITIONING_X[dir][14] && - monster._position.y == SCREEN_POSITIONING_Y[dir][14]) { + if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][14]) && + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][14])) { monster._isAttacking = true; if (!_wo[22] && !_wo[27]) { @@ -474,8 +475,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } } - if (monster._position.x == SCREEN_POSITIONING_X[dir][12] && - monster._position.y == SCREEN_POSITIONING_Y[dir][12]) { + if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][12]) && + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][12])) { if (_wo[27]) { } else if (_wo[22] && _wo[23]) { } else if (_wo[22] & _wo[20]) { @@ -493,8 +494,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } } - if (monster._position.x == SCREEN_POSITIONING_X[dir][16] && - monster._position.y == SCREEN_POSITIONING_Y[dir][16]) { + if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][16]) && + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][16])) { if (_wo[27]) { } else if (_wo[22] && _wo[24]) { } else if (_wo[22] & _wo[21]) { @@ -513,8 +514,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } } - if (monster._position.x == SCREEN_POSITIONING_X[dir][27] && - monster._position.y == SCREEN_POSITIONING_Y[dir][27]) { + if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][27]) && + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][27])) { if (!_wo[27] && !_wo[22] && _wo[15]) { monster._isAttacking = true; @@ -531,8 +532,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } } - if (monster._position.x == SCREEN_POSITIONING_X[dir][25] && - monster._position.y == SCREEN_POSITIONING_Y[dir][25]) { + if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][25]) && + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][25])) { if (_wo[27] || _wo[22]) { } else if (_wo[15] && _wo[17]) { } else if (_wo[15] && _wo[12]) { @@ -554,8 +555,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } } - if (monster._position.x == SCREEN_POSITIONING_X[dir][23] && - monster._position.y == SCREEN_POSITIONING_Y[dir][23]) { + if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][23]) && + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][23])) { if (_wo[27]) { } else if (_wo[22] && _wo[20]) { } else if (_wo[22] && _wo[23]) { @@ -572,8 +573,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } } - if (monster._position.x == SCREEN_POSITIONING_X[dir][29] && - monster._position.y == SCREEN_POSITIONING_Y[dir][29]) { + if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][29]) && + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][29])) { if (_wo[27] || _wo[22]) { } else if (_wo[15] && _wo[19]) { } else if (_wo[15] && _wo[14]) { @@ -595,8 +596,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } } - if (monster._position.x == SCREEN_POSITIONING_X[dir][31] && - monster._position.y == SCREEN_POSITIONING_Y[dir][31]) { + if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][31]) && + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][31])) { if (_wo[27]) { } else if (_wo[22] && _wo[21]) { } else if (_wo[22] && _wo[24]) { @@ -642,7 +643,7 @@ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster drawStruct._flags = MONSTER_EFFECT_FLAGS[monster._effect2][monster._effect3]; } -void InterfaceMap::setIndoorObjects() { +void InterfaceMap::setIndoorsObjects() { Common::Point mazePos = _vm->_party._mazePosition; Direction dir = _vm->_party._mazeDirection; Common::Point pt; diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 8013228122..a77d29e091 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -107,7 +107,7 @@ public: void setIndoorsAttackingMonsters(); - void setIndoorObjects(); + void setIndoorsObjects(); void setIndoorsWallPics(); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index a5a40c9029..6bd1ed09ba 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -950,7 +950,7 @@ void Map::load(int mapId) { if (mapId != 0) { // Load in the maze's data file Common::String datName = Common::String::format("maze%c%03d.dat", - (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId); + (mapId >= 100) ? 'x' : '0', mapId); File datFile(datName); mazeData->synchronize(datFile); datFile.close(); @@ -1435,11 +1435,11 @@ int Map::getCell(int idx) { _currentWall._data = 0x8888; return 0x8888; } - - _mazeDataIndex = 0; - while (_mazeData[_mazeDataIndex]._mazeId != mapId) - ++_mazeDataIndex; } + + _mazeDataIndex = 0; + while (_mazeData[_mazeDataIndex]._mazeId != mapId) + ++_mazeDataIndex; } MazeWallLayers &wallLayers = _mazeData[_mazeDataIndex]._wallData[pt.y][pt.x]; -- cgit v1.2.3 From d37e3d6e747877187fe6c1179070f666f9bbb778 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 16 Jan 2015 22:19:36 -0500 Subject: XEEN: Minor cleanup and renamings --- engines/xeen/interface.cpp | 4 ++-- engines/xeen/interface_map.cpp | 24 ++++++++++++------------ engines/xeen/interface_map.h | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index f3060c2cf4..87259d83bf 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -661,7 +661,7 @@ void Interface::draw3d(bool updateFlag) { } } - setIndoorsAttackingMonsters(); + setIndoorsMonsters(); setIndoorsObjects(); setIndoorsWallPics(); @@ -756,7 +756,7 @@ void Interface::startup() { animate3d(); if (_vm->_map->_isOutdoors) { - setIndoorsAttackingMonsters(); + setIndoorsMonsters(); setIndoorsObjects(); } else { setOutdoorsMonsters(); diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 6780a5c2ee..45751f8b34 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -374,7 +374,7 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) { _combatFloatCounter = 0; } -void InterfaceMap::setIndoorsAttackingMonsters() { +void InterfaceMap::setIndoorsMonsters() { Combat &combat = *_vm->_combat; Map &map = *_vm->_map; Common::Point mazePos = _vm->_party._mazePosition; @@ -426,7 +426,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][5]) && - monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][5])) { + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][5])) { if (_wo[27] && _wo[25]) { } else if (_wo[27] && _wo[28]) { } else if (_wo[23] & _wo[25]) { @@ -442,7 +442,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][9]) && - monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][9])) { + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][9])) { if (_wo[27] && _wo[26]) { } else if (_wo[27] && _wo[29]) { } else if (_wo[24] & _wo[26]) { @@ -458,7 +458,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][14]) && - monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][14])) { + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][14])) { monster._isAttacking = true; if (!_wo[22] && !_wo[27]) { @@ -476,7 +476,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][12]) && - monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][12])) { + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][12])) { if (_wo[27]) { } else if (_wo[22] && _wo[23]) { } else if (_wo[22] & _wo[20]) { @@ -495,7 +495,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][16]) && - monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][16])) { + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][16])) { if (_wo[27]) { } else if (_wo[22] && _wo[24]) { } else if (_wo[22] & _wo[21]) { @@ -515,8 +515,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][27]) && - monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][27])) { - if (!_wo[27] && !_wo[22] && _wo[15]) { + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][27])) { + if (!_wo[27] && !_wo[22] && !_wo[15]) { monster._isAttacking = true; if (combat._attackMonsters[9] == -1) { @@ -533,7 +533,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][25]) && - monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][25])) { + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][25])) { if (_wo[27] || _wo[22]) { } else if (_wo[15] && _wo[17]) { } else if (_wo[15] && _wo[12]) { @@ -556,7 +556,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][23]) && - monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][23])) { + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][23])) { if (_wo[27]) { } else if (_wo[22] && _wo[20]) { } else if (_wo[22] && _wo[23]) { @@ -574,7 +574,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][29]) && - monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][29])) { + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][29])) { if (_wo[27] || _wo[22]) { } else if (_wo[15] && _wo[19]) { } else if (_wo[15] && _wo[14]) { @@ -597,7 +597,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() { } if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][31]) && - monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][31])) { + monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][31])) { if (_wo[27]) { } else if (_wo[22] && _wo[21]) { } else if (_wo[22] && _wo[24]) { diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index a77d29e091..2376f8f55b 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -105,7 +105,7 @@ public: public: InterfaceMap(XeenEngine *vm); - void setIndoorsAttackingMonsters(); + void setIndoorsMonsters(); void setIndoorsObjects(); -- cgit v1.2.3 From e0305aa9d94b44aa7d1061e0782f071181f7f7e7 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 16 Jan 2015 22:31:27 -0500 Subject: XEEN: Fix loading correct monster sprites --- engines/xeen/map.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 6bd1ed09ba..3e4139628e 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1045,10 +1045,10 @@ void Map::load(int mapId) { // Load sprites for the monsters for (uint i = 0; i < _mobData._monsterSprites.size(); ++i) { - filename = Common::String::format("%03d.mon", _mobData._objectSprites[i]._spriteId); + filename = Common::String::format("%03d.mon", _mobData._monsterSprites[i]._spriteId); _mobData._monsterSprites[i]._sprites.load(filename); - filename = Common::String::format("%03d.att", _mobData._objectSprites[i]._spriteId); + filename = Common::String::format("%03d.att", _mobData._monsterSprites[i]._spriteId); _mobData._monsterSprites[i]._attackSprites.load(filename); } -- cgit v1.2.3 From b860745a8e1a89bfd34e1c3f263597bef59126ca Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 17 Jan 2015 09:11:05 -0500 Subject: XEEN: Add support for horizontally flipped sprites --- engines/xeen/interface_map.cpp | 1 + engines/xeen/map.cpp | 4 ++-- engines/xeen/screen.cpp | 2 +- engines/xeen/sprites.cpp | 54 ++++++++++++++++++++++-------------------- engines/xeen/sprites.h | 2 +- 5 files changed, 33 insertions(+), 30 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 45751f8b34..ba6288eacb 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -1913,6 +1913,7 @@ void InterfaceMap::drawIndoors() { // WORKAROUND: Original did an array lookup on _skySprites. // Was this a feature for multiple skys that was abandoned? + assert(!map._currentSky); _indoorList[0]._sprites = &map._skySprites; _indoorList[0]._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 3e4139628e..86f60852f6 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1062,7 +1062,7 @@ void Map::load(int mapId) { if (_isOutdoors) { warning("TODO"); // Sound loading - _skySprites.load(isDarkCc ? "sky.sky" : "night.sky"); + _skySprites.load(isDarkCc ? "night.sky" : "sky.sky"); _groundSprites.load("water.out"); _tileSprites.load("outdoor.til"); outdoorList._skySprite._sprites = &_skySprites; @@ -1082,7 +1082,7 @@ void Map::load(int mapId) { } else { warning("TODO"); // Sound loading - _skySprites.load(isDarkCc ? "sky.sky" : "night.sky"); + _skySprites.load(isDarkCc ? "night.sky" : "sky.sky"); _mazeSkySprites.load(Common::String::format("%s.sky", TERRAIN_TYPES[_mazeData[0]._wallKind])); _groundSprites.load(Common::String::format("%s.gnd", diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 7b6f972268..b1b42ac551 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -178,7 +178,7 @@ void Window::drawList(DrawStruct *items, int count) { // TODO: There are two sprite calls in this method. Figure out why items->_sprites->draw(screen, items->_frame, - Common::Point(items->_x, items->_y)); + Common::Point(items->_x, items->_y), items->_flags); } } diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index df1debab21..85ca91bde3 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -85,7 +85,7 @@ void SpriteResource::clear() { _filesize = 0; } -void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const { +void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, int flags) const { // Get cell header Common::MemoryReadStream f(_data, _filesize); f.seek(offset); @@ -94,6 +94,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi int yOffset = f.readUint16LE(); int height = f.readUint16LE(); + bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0; + int xInc = flipped ? -1 : 1; + if (dest.w < (xOffset + width) || dest.h < (yOffset + height)) dest.create(xOffset + width, yOffset + height); @@ -116,9 +119,11 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi } else { // Skip the transparent pixels at the beginning of the scan line int xPos = f.readByte() + xOffset; ++byteCount; - byte *destP = (byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos); const byte *lineStartP = (const byte *)dest.getBasePtr(0, destPos.y + yPos); const byte *lineEndP = (const byte *)dest.getBasePtr(dest.w, destPos.y + yPos); + byte *destP = !flipped ? + (byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos) : + (byte *)dest.getBasePtr(destPos.x + width - xPos, destPos.y + yPos); while (byteCount < lineLength) { // The next byte is an opcode that determines what @@ -134,21 +139,20 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi case 1: // The following len + 33 bytes are stored as indexes into the color table. for (int i = 0; i < opcode + 1; ++i, ++xPos) { byte b = f.readByte(); - if (destP < lineStartP || destP >= lineEndP) - ++destP; - else - *destP++ = b; ++byteCount; + + if (destP >= lineStartP && destP < lineEndP) + *destP = b; + destP += xInc; } break; case 2: // The following byte is an index into the color table, draw it len + 3 times. opr1 = f.readByte(); ++byteCount; for (int i = 0; i < len + 3; ++i, ++xPos) { - if (destP < lineStartP || destP >= lineEndP) - ++destP; - else - *destP++ = opr1; + if (destP >= lineStartP && destP < lineEndP) + *destP = opr1; + destP += xInc; } break; @@ -159,10 +163,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi for (int i = 0; i < len + 4; ++i, ++xPos) { byte b = f.readByte(); - if (destP < lineStartP || destP >= lineEndP) - ++destP; - else - *destP++ = b; + if (destP >= lineStartP && destP < lineEndP) + *destP = b; + destP += xInc; } f.seek(pos, SEEK_SET); @@ -173,17 +176,19 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi opr2 = f.readByte(); ++byteCount; for (int i = 0; i < len + 2; ++i, xPos += 2) { if (destP < lineStartP || destP >= (lineEndP - 1)) { - destP += 2; + destP += 2 * xInc; } else { - *destP++ = opr1; - *destP++ = opr2; + *destP = opr1; + destP += xInc; + *destP = opr2; + destP += xInc; } } break; case 5: // Skip len + 1 pixels filling them with the transparent color. xPos += len + 1; - destP += len + 1; + destP += (len + 1) * xInc; break; case 6: // Pattern command. @@ -194,10 +199,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi opr1 = f.readByte(); ++byteCount; for (int i = 0; i < len + 3; ++i, ++xPos) { - if (destP < lineStartP || destP >= lineEndP) - ++destP; - else - *destP++ = opr1; + if (destP >= lineStartP && destP < lineEndP) + *destP = opr1; + destP += xInc; opr1 += patternSteps[cmd + (i % 2)]; } break; @@ -219,11 +223,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, int flags) const { // TODO: Support the different flags - assert(!flags); - - drawOffset(dest, _index[frame]._offset1, destPos); + drawOffset(dest, _index[frame]._offset1, destPos, flags); if (_index[frame]._offset2) - drawOffset(dest, _index[frame]._offset2, destPos); + drawOffset(dest, _index[frame]._offset2, destPos, flags); } void SpriteResource::draw(XSurface &dest, int frame) const { diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index 59c1ed1d48..c240059c15 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -45,7 +45,7 @@ private: int32 _filesize; byte *_data; - void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const; + void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, int flags) const; public: SpriteResource(); SpriteResource(const Common::String &filename); -- cgit v1.2.3 From 258ab0209679a84e0e8ef96718fe442dd47e2d7d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 18 Jan 2015 08:57:23 -0500 Subject: XEEN: Load sprites from the correct archive --- engines/xeen/files.cpp | 17 ++++++++++++++--- engines/xeen/files.h | 2 ++ engines/xeen/interface_map.cpp | 4 +++- engines/xeen/map.cpp | 37 ++++++++++++++++++++++++++----------- engines/xeen/map.h | 5 +++-- engines/xeen/sprites.cpp | 9 ++++++++- engines/xeen/sprites.h | 4 ++++ 7 files changed, 60 insertions(+), 18 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index 8ab1f35fcb..f15a08b184 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -198,11 +198,22 @@ Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::S */ FileManager::FileManager(XeenEngine *vm) { Common::File f; + int sideNum = 0; _isDarkCc = vm->getGameID() != GType_Clouds; - if (_isDarkCc) - SearchMan.add("dark", new CCArchive("dark.cc", "dark", true)); - SearchMan.add("xeen", new CCArchive("xeen.cc", "xeen", true)); + _sideArchives[0] = _sideArchives[1] = nullptr; + + if (vm->getGameID() != GType_DarkSide) { + _sideArchives[0] = new CCArchive("xeen.cc", "xeen", true); + SearchMan.add("xeen", _sideArchives[0]); + sideNum = 1; + } + + if (vm->getGameID() == GType_DarkSide || vm->getGameID() == GType_WorldOfXeen) { + _sideArchives[sideNum] = new CCArchive("dark.cc", "dark", true); + SearchMan.add("dark", _sideArchives[sideNum]); + } + SearchMan.add("intro", new CCArchive("intro.cc", "intro", true)); } diff --git a/engines/xeen/files.h b/engines/xeen/files.h index a8343c1653..f350e34166 100644 --- a/engines/xeen/files.h +++ b/engines/xeen/files.h @@ -33,6 +33,7 @@ namespace Xeen { class XeenEngine; +class CCArchive; #define SYNC_AS(SUFFIX,STREAM,TYPE,SIZE) \ template<typename T> \ @@ -53,6 +54,7 @@ class XeenEngine; class FileManager { public: bool _isDarkCc; + CCArchive *_sideArchives[2]; public: FileManager(XeenEngine *vm); diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index ba6288eacb..1310e19950 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -855,7 +855,7 @@ void InterfaceMap::setIndoorsObjects() { } else if (_wo[22] && _wo[24]) { } else if (_wo[21] && _wo[19]) { } else if (_wo[24] && _wo[19]) { - } else if (!_wo[14] && !_wo[10] && !_indoorList._objects11._frame == -1) { + } else if (!_wo[14] && !_wo[10] && _indoorList._objects11._frame == -1) { _indoorList._objects11._x = INDOOR_OBJECT_X[listOffset][11]; _indoorList._objects11._y = INDOOR_OBJECT_Y[listOffset][11]; _indoorList._objects11._frame = mazeObject._frame; @@ -1948,6 +1948,8 @@ void InterfaceMap::drawIndoors() { _charsShooting = _isShooting; // TODO + SpriteResource *spr = _vm->_map->_mobData._objects[41]._sprites; + spr->draw(*_vm->_screen, 0); } } // End of namespace Xeen diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 86f60852f6..10143edec3 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -850,8 +850,9 @@ void AnimationInfo::load(const Common::String &name) { Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { _townPortalSide = 0; - _sideObj = 0; - _sideMon = 0; + _sideObjects = 0; + _sideMonsters = 0; + _sidePictures = 0; _isOutdoors = false; _stepped = false; _mazeDataIndex = 0; @@ -871,6 +872,7 @@ void Map::load(int mapId) { Screen &screen = *_vm->_screen; IndoorDrawList &indoorList = _vm->_interface->_indoorList; OutdoorDrawList &outdoorList = _vm->_interface->_outdoorList; + int sideNumber = 0; if (_vm->_falling) { Window &w = screen._windows[9]; @@ -884,7 +886,9 @@ void Map::load(int mapId) { _vm->_party._mazeId = mapId; _vm->_events->clearEvents(); - + _sideObjects = 1; + _sideMonsters = 1; + _sidePictures = 1; if (mapId >= 113 && mapId <= 127) { _townPortalSide = 0; } else { @@ -896,6 +900,9 @@ void Map::load(int mapId) { _animationInfo.load("clouds.dat"); _monsterData.load("xeen.mon"); _wallPicSprites.load("xeenpic.dat"); + _sidePictures = 0; + _sideMonsters = 0; + _sideObjects = 0; } else { switch (mapId) { case 113: @@ -906,7 +913,7 @@ void Map::load(int mapId) { _animationInfo.load("clouds.dat"); _monsterData.load("dark.mon"); _wallPicSprites.load("darkpic.dat"); - _sideObj = 0; + _sideObjects = 0; break; case 117: case 118: @@ -916,8 +923,8 @@ void Map::load(int mapId) { _animationInfo.load("clouds.dat"); _monsterData.load("xeen.mon"); _wallPicSprites.load("darkpic.dat"); - _sideObj = 0; - _sideMon = 0; + _sideObjects = 0; + _sideMonsters = 0; break; case 125: case 126: @@ -925,6 +932,8 @@ void Map::load(int mapId) { _animationInfo.load("clouds.dat"); _monsterData.load("dark.mon"); _wallPicSprites.load("xeenpic.dat"); + _sideObjects = 0; + _sidePictures = 0; break; default: _animationInfo.load("dark.dat"); @@ -1034,28 +1043,34 @@ void Map::load(int mapId) { filename = "085.obj"; _mobData._objectSprites[0]._spriteId = 85; } else { - filename = Common::String::format("%03d.%cbj", + filename = Common::String::format("xeen|%03d.%cbj", _mobData._objectSprites[i]._spriteId, _mobData._objectSprites[i]._spriteId >= 100 ? '0' : 'o'); } // Read in the object sprites - _mobData._objectSprites[i]._sprites.load(filename); + _mobData._objectSprites[i]._sprites.load(filename, + *_vm->_files->_sideArchives[_sideObjects]); } // Load sprites for the monsters for (uint i = 0; i < _mobData._monsterSprites.size(); ++i) { + CCArchive *archive = _vm->_files->_sideArchives[ + _mobData._monsterSprites[i]._spriteId == 91 && _vm->getGameID() == GType_WorldOfXeen ? + 0 : _sideMonsters]; + filename = Common::String::format("%03d.mon", _mobData._monsterSprites[i]._spriteId); - _mobData._monsterSprites[i]._sprites.load(filename); + _mobData._monsterSprites[i]._sprites.load(filename, *archive); filename = Common::String::format("%03d.att", _mobData._monsterSprites[i]._spriteId); - _mobData._monsterSprites[i]._attackSprites.load(filename); + _mobData._monsterSprites[i]._attackSprites.load(filename, *archive); } // Load wall picture sprite resources for (uint i = 0; i < _mobData._wallItemSprites.size(); ++i) { filename = Common::String::format("%03d.pic", _mobData._wallItems[i]._spriteId); - _mobData._wallItemSprites[i]._sprites.load(filename); + _mobData._wallItemSprites[i]._sprites.load(filename, + *_vm->_files->_sideArchives[_sidePictures]); } // Handle loading miscellaneous sprites for the map diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 8e6fee2811..5c3e5a3fed 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -356,8 +356,9 @@ private: Common::String _mazeName; SpriteResource _wallPicSprites; int _townPortalSide; - int _sideObj; - int _sideMon; + int _sidePictures; + int _sideObjects; + int _sideMonsters; bool _stepped; int _mazeDataIndex; bool _currentSteppedOn; diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 85ca91bde3..8a14ec0178 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -59,9 +59,16 @@ SpriteResource &SpriteResource::operator=(const SpriteResource &src) { } void SpriteResource::load(const Common::String &filename) { - // Open the resource File f(filename); + load(f); +} + +void SpriteResource::load(const Common::String &filename, Common::Archive &archive) { + File f(filename, archive); + load(f); +} +void SpriteResource::load(Common::SeekableReadStream &f) { // Read in a copy of the file _filesize = f.size(); delete[] _data; diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index c240059c15..973875cfed 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -45,6 +45,8 @@ private: int32 _filesize; byte *_data; + void load(Common::SeekableReadStream &f); + void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, int flags) const; public: SpriteResource(); @@ -56,6 +58,8 @@ public: void load(const Common::String &filename); + void load(const Common::String &filename, Common::Archive &archive); + void clear(); void draw(XSurface &dest, int frame, const Common::Point &destPos, int flags = 0) const; -- cgit v1.2.3 From ceeda17ab1fae75e28c4d15e3e829a02615ffc81 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 18 Jan 2015 15:59:07 -0500 Subject: XEEN: Remove old test sprite from being displayed --- engines/xeen/interface_map.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 1310e19950..d34373ea3d 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -1946,10 +1946,6 @@ void InterfaceMap::drawIndoors() { } _charsShooting = _isShooting; - - // TODO - SpriteResource *spr = _vm->_map->_mobData._objects[41]._sprites; - spr->draw(*_vm->_screen, 0); } } // End of namespace Xeen -- cgit v1.2.3 From 9925453774c803921f5ed3503bbd448b1888f011 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 18 Jan 2015 17:17:55 -0500 Subject: XEEN: Fix loading of MonsterData array --- engines/xeen/map.cpp | 21 +++++++++++++-------- engines/xeen/map.h | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 10143edec3..36232aeb91 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -94,13 +94,18 @@ MonsterStruct::MonsterStruct(Common::String name, int experience, int hp, int ac void MonsterStruct::synchronize(Common::SeekableReadStream &s) { - _experience = s.readByte(); - _hp = s.readByte(); + char name[16]; + s.read(name, 16); + name[15] = '\0'; + _name = Common::String(name); + + _experience = s.readUint32LE(); + _hp = s.readUint16LE(); _accuracy = s.readByte(); _speed = s.readByte(); _numberOfAttacks = s.readByte(); - _hatesClass = CLASS_KNIGHT; - _strikes = s.readByte(); + _hatesClass = (CharacterClass)s.readByte(); + _strikes = s.readUint16LE(); _dmgPerStrike = s.readByte(); _attackType = (DamageType)s.readByte(); _specialAttack = (SpecialAttack)s.readByte(); @@ -115,18 +120,18 @@ void MonsterStruct::synchronize(Common::SeekableReadStream &s) { _magicResistence = s.readByte(); _phsyicalResistence = s.readByte(); _field29 = s.readByte(); - _gold = s.readByte(); + _gold = s.readUint16LE(); _gems = s.readByte(); _itemDrop = s.readByte(); - _flying = s.readByte(); + _flying = s.readByte() != 0; _imageNumber = s.readByte(); _loopAnimation = s.readByte(); _animationEffect = s.readByte(); _field32 = s.readByte(); - char attackVoc[9]; + char attackVoc[10]; s.read(attackVoc, 9); - attackVoc[8] = '\0'; + attackVoc[9] = '\0'; _attackVoc = Common::String(attackVoc); } diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 5c3e5a3fed..ec9604c849 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -89,7 +89,7 @@ public: int _gold; int _gems; int _itemDrop; - int _flying; + bool _flying; int _imageNumber; int _loopAnimation; int _animationEffect; -- cgit v1.2.3 From f18a8c364b2b2f608081bb79cad54de3abacd111 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 18 Jan 2015 17:35:17 -0500 Subject: XEEN: Convert default values for monsters flying flags from int to bool --- engines/xeen/map.cpp | 192 +++++++++++++++++++++++++-------------------------- engines/xeen/map.h | 2 +- 2 files changed, 97 insertions(+), 97 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 36232aeb91..0623772953 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -77,7 +77,7 @@ MonsterStruct::MonsterStruct(Common::String name, int experience, int hp, int ac int fireResistence, int electricityResistence, int coldResistence, int poisonResistence, int energyResistence, int magicResistence, int phsyicalResistence, int field29, int gold, int gems, int itemDrop, - int flying, int imageNumber, int loopAnimation, int animationEffect, + bool flying, int imageNumber, int loopAnimation, int animationEffect, int field32, Common::String attackVoc): _name(name), _experience(experience), _hp(hp), _accuracy(accuracy), _speed(speed), _numberOfAttacks(numberOfAttacks), _hatesClass(hatesClass), @@ -138,339 +138,339 @@ void MonsterStruct::synchronize(Common::SeekableReadStream &s) { MonsterData::MonsterData() { push_back(MonsterStruct("", 0, 0, 0, 0, 0, CLASS_KNIGHT, 1, 1, DT_PHYSICAL, SA_NONE, 1, 0, MONSTER_0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 100, "Slime")); + 0, false, 0, 0, 0, 100, "Slime")); push_back(MonsterStruct("Whirlwind", 250000, 1000, 10, 250, 1, CLASS_15, 5, 100, DT_PHYSICAL, SA_CONFUSE, 250, 0, MONSTER_0, 100, - 100, 100, 100, 0, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 176, + 100, 100, 100, 0, 0, 100, 0, 0, 0, 0, false, 1, 0, 0, 176, "airmon")); push_back(MonsterStruct("Annihilator", 1000000, 1500, 40, 200, 12, CLASS_16, 5, 50, DT_ENERGY, SA_NONE, 1, 1, MONSTER_0, 80, 80, 100, - 100, 0, 0, 80, 0, 0, 0, 0, 0, 2, 0, 0, 102, "alien1")); + 100, 0, 0, 80, 0, 0, 0, 0, false, 2, 0, 0, 102, "alien1")); push_back(MonsterStruct("Autobot", 1000000, 2500, 100, 200, 2, CLASS_16, 5, 100, DT_ENERGY, SA_NONE, 1, 0, MONSTER_0, 50, 50, 100, - 100, 0, 0, 50, 0, 0, 0, 0, 1, 3, 0, 0, 101, "alien2")); + 100, 0, 0, 50, 0, 0, 0, 0, true, 3, 0, 0, 101, "alien2")); push_back(MonsterStruct("Sewer Stalker", 50000, 250, 30, 25, 1, CLASS_16, 3, 100, DT_PHYSICAL, SA_NONE, 50, 0, MONSTER_ANIMAL, 0, - 0, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 113, + 0, 50, 50, 0, 0, 0, 0, 0, 0, 0, false, 4, 0, 0, 113, "iguana")); push_back(MonsterStruct("Armadillo", 60000, 800, 50, 15, 1, CLASS_16, 100, 6, DT_PHYSICAL, SA_BREAKWEAPON, 60, 0, MONSTER_ANIMAL, - 50, 0, 80, 80, 50, 0, 50, 0, 0, 0, 0, 0, 5, 1, 0, 113, + 50, 0, 80, 80, 50, 0, 50, 0, 0, 0, 0, false, 5, 1, 0, 113, "unnh")); push_back(MonsterStruct("Barbarian", 5000, 50, 5, 40, 3, CLASS_SORCERER, 1, 20, DT_PHYSICAL, SA_NONE, 20, 1, MONSTER_HUMANOID, 0, 0, - 0, 0, 0, 0, 0, 0, 100, 0, 3, 0, 6, 0, 0, 100, + 0, 0, 0, 0, 0, 0, 100, 0, 3, false, 6, 0, 0, 100, "barbarch")); push_back(MonsterStruct("Electrapede", 10000, 200, 10, 50, 1, CLASS_PALADIN, 50, 1, DT_ELECTRICAL, SA_PARALYZE, 1, 0, MONSTER_INSECT, 50, 100, 50, 50, 50, 0, 0, 0, 0, 0, 0, - 0, 7, 1, 0, 107, "centi")); + false, 7, 1, 0, 107, "centi")); push_back(MonsterStruct("Cleric of Mok", 30000, 125, 10, 40, 1, CLASS_CLERIC, 250, 1, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, - 10, 100, 10, 10, 10, 10, 0, 0, 0, 10, 0, 0, 8, 0, 0, + 10, 100, 10, 10, 10, 10, 0, 0, 0, 10, 0, false, 8, 0, 0, 117, "cleric")); push_back(MonsterStruct("Mok Heretic", 50000, 150, 12, 50, 1, CLASS_CLERIC, 500, 1, DT_1, SA_NONE, 1, 1, MONSTER_HUMANOID, 20, 50, - 20, 20, 20, 30, 0, 0, 0, 25, 4, 0, 8, 0, 0, 117, + 20, 20, 20, 30, 0, 0, 0, 25, 4, false, 8, 0, 0, 117, "cleric")); push_back(MonsterStruct("Mantis Ant", 40000, 300, 30, 40, 2, CLASS_16, 2, 100, DT_PHYSICAL, SA_POISON, 30, 0, MONSTER_INSECT, 0, 0, - 0, 100, 0, 0, 30, 0, 0, 0, 0, 0, 10, 0, 0, 104, + 0, 100, 0, 0, 30, 0, 0, 0, 0, false, 10, 0, 0, 104, "spell001")); push_back(MonsterStruct("Cloud Dragon", 500000, 2000, 40, 150, 1, CLASS_15, 600, 1, DT_COLD, SA_NONE, 1, 1, MONSTER_DRAGON, 0, 50, - 100, 100, 50, 25, 50, 0, 0, 10, 0, 0, 11, 0, 0, 140, + 100, 100, 50, 25, 50, 0, 0, 10, 0, false, 11, 0, 0, 140, "tiger1")); push_back(MonsterStruct("Phase Dragon", 2000000, 4000, 80, 200, 1, CLASS_15, 750, 1, DT_COLD, SA_NONE, 1, 1, MONSTER_DRAGON, 0, 50, - 100, 100, 80, 50, 50, 0, 0, 20, 0, 0, 11, 0, 10, 140, + 100, 100, 80, 50, 50, 0, 0, 20, 0, false, 11, 0, 10, 140, "Begger")); push_back(MonsterStruct("Green Dragon", 500000, 2500, 50, 150, 1, CLASS_15, 500, 1, DT_FIRE, SA_NONE, 1, 1, MONSTER_DRAGON, 100, - 50, 0, 100, 50, 25, 50, 0, 0, 10, 0, 0, 13, 0, 0, 140, + 50, 0, 100, 50, 25, 50, 0, 0, 10, 0, false, 13, 0, 0, 140, "tiger1")); push_back(MonsterStruct("Energy Dragon", 2000000, 5000, 100, 250, 1, CLASS_15, 1000, 1, DT_ENERGY, SA_NONE, 1, 1, MONSTER_DRAGON, 80, - 80, 60, 100, 100, 30, 50, 0, 0, 20, 0, 0, 13, 0, 7, + 80, 60, 100, 100, 30, 50, 0, 0, 20, 0, false, 13, 0, 7, 140, "begger")); push_back(MonsterStruct("Dragon Mummy", 2000000, 3000, 30, 100, 1, CLASS_CLERIC, 2000, 2, DT_PHYSICAL, SA_DISEASE, 200, 0, MONSTER_DRAGON, 0, 80, 100, 100, 0, 10, 90, 0, 0, 0, - 0, 0, 15, 0, 0, 140, "dragmum")); + 0, false, 15, 0, 0, 140, "dragmum")); push_back(MonsterStruct("Scraps", 2000000, 3000, 30, 100, 1, CLASS_16, 2000, 2, DT_PHYSICAL, SA_NONE, 200, 0, MONSTER_DRAGON, 0, 80, - 100, 100, 0, 10, 90, 0, 0, 0, 0, 0, 15, 0, 0, 140, + 100, 100, 0, 10, 90, 0, 0, 0, 0, false, 15, 0, 0, 140, "dragmum")); push_back(MonsterStruct("Earth Blaster", 250000, 1000, 10, 100, 1, CLASS_15, 5, 100, DT_PHYSICAL, SA_NONE, 200, 0, MONSTER_0, 100, 90, - 90, 100, 0, 0, 90, 0, 0, 0, 0, 0, 17, 0, 0, 100, + 90, 100, 0, 0, 90, 0, 0, 0, 0, false, 17, 0, 0, 100, "earthmon")); push_back(MonsterStruct("Beholder Bat", 10000, 75, 15, 80, 1, CLASS_15, 5, 5, DT_FIRE, SA_NONE, 1, 0, MONSTER_0, 100, 50, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 18, 0, 0, 120, "eyeball")); + 0, 0, 0, 0, 0, true, 18, 0, 0, 120, "eyeball")); push_back(MonsterStruct("Fire Blower", 250000, 1000, 20, 60, 1, CLASS_15, 5, 100, DT_FIRE, SA_NONE, 1, 0, MONSTER_0, 100, 50, 0, - 100, 50, 0, 50, 0, 0, 0, 0, 0, 19, 0, 0, 110, "fire")); + 100, 50, 0, 50, 0, 0, 0, 0, false, 19, 0, 0, 110, "fire")); push_back(MonsterStruct("Hell Hornet", 50000, 250, 30, 50, 2, CLASS_DRUID, 2, 250, DT_POISON, SA_WEAKEN, 1, 0, MONSTER_INSECT, 50, - 50, 50, 100, 50, 0, 50, 0, 0, 0, 0, 1, 20, 0, 0, 123, + 50, 50, 100, 50, 0, 50, 0, 0, 0, 0, true, 20, 0, 0, 123, "insect")); push_back(MonsterStruct("Gargoyle", 30000, 150, 35, 30, 2, CLASS_16, 5, 50, DT_PHYSICAL, SA_NONE, 60, 0, MONSTER_0, 0, 0, 0, 0, 0, - 20, 0, 0, 0, 0, 0, 0, 21, 0, 10, 100, "gargrwl")); + 20, 0, 0, 0, 0, 0, false, 21, 0, 10, 100, "gargrwl")); push_back(MonsterStruct("Giant", 100000, 500, 25, 45, 2, CLASS_16, 100, 5, DT_PHYSICAL, SA_UNCONSCIOUS, 100, 0, MONSTER_0, 0, 0, - 0, 0, 0, 0, 0, 0, 1000, 0, 5, 0, 22, 0, 0, 100, + 0, 0, 0, 0, 0, 0, 1000, 0, 5, false, 22, 0, 0, 100, "giant")); push_back(MonsterStruct("Goblin", 1000, 10, 5, 30, 2, CLASS_16, 2, 6, DT_PHYSICAL, SA_NONE, 1, 0, MONSTER_0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 131, "gremlin")); + 0, 0, 0, 0, 0, 0, false, 25, 0, 0, 131, "gremlin")); push_back(MonsterStruct("Onyx Golem", 1000000, 10000, 50, 100, 1, CLASS_15, 2, 250, DT_1, SA_DRAINSP, 1, 0, MONSTER_GOLEM, 100, 100, - 100, 100, 100, 100, 50, 0, 0, 100, 0, 1, 24, 0, 10, + 100, 100, 100, 100, 50, 0, 0, 100, 0, true, 24, 0, 10, 100, "golem")); push_back(MonsterStruct("Gremlin", 2000, 20, 7, 35, 2, CLASS_16, 2, 10, DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 101, "gremlink")); + 0, 0, 0, 0, 0, 0, false, 26, 0, 0, 101, "gremlink")); push_back(MonsterStruct("Gremlin Guard", 3000, 50, 10, 35, 2, CLASS_16, 6, 5, DT_PHYSICAL, SA_NONE, 20, 0, MONSTER_0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 101, "gremlink")); + 0, 0, 0, 0, 0, 0, false, 26, 0, 0, 101, "gremlink")); push_back(MonsterStruct("Griffin", 60000, 800, 35, 150, 2, CLASS_KNIGHT, 50, 6, DT_PHYSICAL, SA_NONE, 150, 0, MONSTER_ANIMAL, 0, 0, 0, - 0, 0, 80, 0, 0, 0, 0, 0, 0, 27, 0, 0, 120, "screech")); + 0, 0, 80, 0, 0, 0, 0, 0, false, 27, 0, 0, 120, "screech")); push_back(MonsterStruct("Gamma Gazer", 1000000, 5000, 60, 200, 7, CLASS_16, 10, 20, DT_ENERGY, SA_NONE, 1, 0, MONSTER_0, 100, 100, 0, - 100, 100, 0, 60, 0, 0, 0, 0, 0, 28, 0, 0, 140, "hydra")); + 100, 100, 0, 60, 0, 0, 0, 0, false, 28, 0, 0, 140, "hydra")); push_back(MonsterStruct("Iguanasaurus", 100000, 2500, 20, 30, 1, CLASS_16, 10, 50, DT_PHYSICAL, SA_INSANE, 150, 0, MONSTER_ANIMAL, 50, - 50, 50, 50, 50, 0, 20, 0, 0, 0, 0, 0, 29, 0, 0, 113, + 50, 50, 50, 50, 0, 20, 0, 0, 0, 0, false, 29, 0, 0, 113, "iguana")); push_back(MonsterStruct("Slayer Knight", 50000, 500, 30, 50, 1, CLASS_PALADIN, 2, 250, DT_PHYSICAL, SA_NONE, 100, 0, MONSTER_HUMANOID, - 50, 50, 50, 50, 50, 0, 0, 0, 50, 0, 5, 0, 30, 0, 0, + 50, 50, 50, 50, 50, 0, 0, 0, 50, 0, 5, false, 30, 0, 0, 141, "knight")); push_back(MonsterStruct("Death Knight", 100000, 750, 50, 80, 2, CLASS_PALADIN, 2, 250, DT_PHYSICAL, SA_NONE, 150, 0, MONSTER_HUMANOID, - 50, 50, 50, 50, 50, 10, 0, 0, 100, 0, 6, 0, 30, 0, 0, + 50, 50, 50, 50, 50, 10, 0, 0, 100, 0, 6, false, 30, 0, 0, 141, "knight")); push_back(MonsterStruct("Lava Dweller", 500000, 1500, 30, 40, 1, CLASS_15, 5, 100, DT_FIRE, SA_NONE, 1, 0, MONSTER_0, 100, 100, 0, - 100, 50, 0, 50, 0, 0, 0, 0, 0, 19, 0, 0, 110, "fire")); + 100, 50, 0, 50, 0, 0, 0, 0, false, 19, 0, 0, 110, "fire")); push_back(MonsterStruct("Lava Roach", 50000, 500, 20, 70, 1, CLASS_16, 5, 50, DT_FIRE, SA_NONE, 1, 0, MONSTER_INSECT, 100, 100, 0, - 100, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 131, "Phantom")); + 100, 0, 0, 0, 0, 0, 0, 0, false, 33, 0, 0, 131, "Phantom")); push_back(MonsterStruct("Power Lich", 200000, 500, 20, 60, 1, CLASS_15, 10, 10, DT_1, SA_UNCONSCIOUS, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0, - 0, 80, 70, 0, 0, 0, 0, 1, 34, 0, 0, 141, "lich")); + 0, 80, 70, 0, 0, 0, 0, true, 34, 0, 0, 141, "lich")); push_back(MonsterStruct("Mystic Mage", 100000, 200, 20, 70, 1, CLASS_15, 10, 20, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_0, 50, 100, - 50, 50, 50, 30, 0, 0, 0, 50, 0, 1, 35, 0, 0, 163, + 50, 50, 50, 30, 0, 0, 0, 50, 0, true, 35, 0, 0, 163, "monsterb")); push_back(MonsterStruct("Magic Mage", 200000, 300, 25, 80, 1, CLASS_15, 10, 30, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_0, 50, 100, 50, - 50, 50, 50, 0, 0, 0, 75, 0, 1, 35, 0, 0, 163, + 50, 50, 50, 0, 0, 0, 75, 0, true, 35, 0, 0, 163, "monsterb")); push_back(MonsterStruct("Minotaur", 250000, 3000, 80, 120, 1, CLASS_16, 100, 4, DT_PHYSICAL, SA_AGING, 150, 0, MONSTER_0, 0, 0, 10, 0, - 0, 50, 60, 0, 0, 0, 0, 0, 37, 0, 0, 141, "stonegol")); + 0, 50, 60, 0, 0, 0, 0, false, 37, 0, 0, 141, "stonegol")); push_back(MonsterStruct("Gorgon", 250000, 4000, 90, 100, 1, CLASS_16, 100, 3, DT_PHYSICAL, SA_STONE, 100, 0, MONSTER_0, 0, 0, 0, 0, - 0, 60, 70, 0, 0, 0, 0, 0, 37, 0, 0, 141, "stonegol")); + 0, 60, 70, 0, 0, 0, 0, false, 37, 0, 0, 141, "stonegol")); push_back(MonsterStruct("Higher Mummy", 100000, 400, 20, 60, 1, CLASS_CLERIC, 10, 40, DT_PHYSICAL, SA_CURSEITEM, 100, 0, MONSTER_UNDEAD, 0, 50, 50, 100, 50, 20, 75, 0, 0, 0, 0, - 0, 39, 0, 0, 141, "mummy")); + false, 39, 0, 0, 141, "mummy")); push_back(MonsterStruct("Orc Guard", 5000, 60, 10, 20, 1, CLASS_12, 3, 10, DT_PHYSICAL, SA_NONE, 20, 0, MONSTER_HUMANOID, 0, 0, - 0, 0, 0, 0, 0, 0, 50, 0, 2, 0, 40, 0, 0, 125, "orc")); + 0, 0, 0, 0, 0, 0, 50, 0, 2, false, 40, 0, 0, 125, "orc")); push_back(MonsterStruct("Octopod", 250000, 2500, 40, 80, 1, CLASS_15, 2, 100, DT_POISON, SA_POISON, 1, 0, MONSTER_ANIMAL, 0, 0, 50, - 100, 0, 0, 0, 0, 0, 0, 0, 1, 41, 0, 0, 101, "photon")); + 100, 0, 0, 0, 0, 0, 0, 0, true, 41, 0, 0, 101, "photon")); push_back(MonsterStruct("Ogre", 10000, 100, 15, 30, 1, CLASS_16, 4, 10, DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 0, 0, 0, 0, 0, - 0, 0, 0, 100, 0, 0, 0, 42, 0, 0, 136, "ogre")); + 0, 0, 0, 100, 0, 0, false, 42, 0, 0, 136, "ogre")); push_back(MonsterStruct("Orc Shaman", 10000, 50, 15, 30, 1, CLASS_15, 5, 5, DT_COLD, SA_SLEEP, 1, 1, MONSTER_HUMANOID, 0, 0, 0, 0, - 0, 10, 0, 0, 75, 10, 2, 0, 43, 0, 0, 125, "fx7")); + 0, 10, 0, 0, 75, 10, 2, false, 43, 0, 0, 125, "fx7")); push_back(MonsterStruct("Sabertooth", 10000, 100, 20, 60, 3, CLASS_16, 5, 10, DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_ANIMAL, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 1, 0, 101, "saber")); + 0, 0, 0, 0, 0, 0, 0, 0, false, 44, 1, 0, 101, "saber")); push_back(MonsterStruct("Sand Flower", 10000, 100, 10, 50, 5, CLASS_16, 5, 5, DT_PHYSICAL, SA_INLOVE, 50, 0, MONSTER_0, 0, 0, 0, 0, - 0, 50, 50, 0, 0, 0, 0, 0, 45, 0, 0, 106, "sand")); + 0, 50, 50, 0, 0, 0, 0, false, 45, 0, 0, 106, "sand")); push_back(MonsterStruct("Killer Cobra", 25000, 1000, 25, 100, 1, CLASS_16, 2, 100, DT_PHYSICAL, SA_AGING, 30, 0, MONSTER_ANIMAL, 0, - 0, 0, 100, 0, 50, 0, 0, 0, 0, 0, 0, 46, 0, 0, 100, + 0, 0, 100, 0, 50, 0, 0, 0, 0, 0, false, 46, 0, 0, 100, "hiss")); push_back(MonsterStruct("Sewer Rat", 2000, 40, 5, 35, 1, CLASS_16, 3, 10, DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_ANIMAL, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 136, "rat")); + 0, 0, 0, 0, 0, 0, 0, 0, false, 47, 0, 0, 136, "rat")); push_back(MonsterStruct("Sewer Slug", 1000, 25, 2, 25, 1, CLASS_16, 2, 10, DT_PHYSICAL, SA_NONE, 5, 0, MONSTER_INSECT, 0, 0, 0, - 100, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 111, "zombie")); + 100, 0, 0, 0, 0, 0, 0, 0, false, 48, 0, 0, 111, "zombie")); push_back(MonsterStruct("Skeletal Lich", 500000, 2000, 30, 200, 1, CLASS_SORCERER, 1000, 1, DT_ENERGY, SA_ERADICATE, 1, 1, MONSTER_UNDEAD, 80, 70, 80, 100, 100, 50, 50, 0, 0, 0, - 0, 0, 49, 0, 0, 140, "elecbolt")); + 0, false, 49, 0, 0, 140, "elecbolt")); push_back(MonsterStruct("Enchantress", 40000, 100, 25, 60, 1, CLASS_CLERIC, 3, 150, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, - 10, 100, 10, 10, 10, 20, 0, 0, 0, 20, 0, 0, 50, 0, 0, + 10, 100, 10, 10, 10, 20, 0, 0, 0, 20, 0, false, 50, 0, 0, 163, "disint")); push_back(MonsterStruct("Sorceress", 80000, 200, 30, 80, 1, CLASS_15, 2, 50, DT_1, SA_NONE, 1, 1, MONSTER_HUMANOID, 10, 20, 10, 10, - 10, 80, 0, 0, 0, 50, 5, 0, 50, 0, 0, 163, "disint")); + 10, 80, 0, 0, 0, 50, 5, false, 50, 0, 0, 163, "disint")); push_back(MonsterStruct("Arachnoid", 4000, 50, 10, 40, 1, CLASS_16, 3, 5, DT_POISON, SA_POISON, 1, 0, MONSTER_INSECT, 0, 0, 0, - 100, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 104, "web")); + 100, 0, 0, 0, 0, 0, 0, 0, false, 52, 0, 0, 104, "web")); push_back(MonsterStruct("Medusa Sprite", 5000, 30, 5, 30, 1, CLASS_RANGER, 3, 3, DT_PHYSICAL, SA_STONE, 10, 0, MONSTER_0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 53, 0, 0, 42, "hiss")); + 0, 0, 0, 0, 0, 0, 0, 0, true, 53, 0, 0, 42, "hiss")); push_back(MonsterStruct("Rogue", 5000, 50, 10, 30, 1, CLASS_ROBBER, 1, 60, DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_HUMANOID, 0, 0, - 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 54, 0, 0, 100, "thief")); + 0, 0, 0, 0, 0, 0, 70, 0, 0, false, 54, 0, 0, 100, "thief")); push_back(MonsterStruct("Thief", 10000, 100, 15, 40, 1, CLASS_ROBBER, 1, 100, DT_PHYSICAL, SA_NONE, 20, 0, MONSTER_HUMANOID, 0, 0, - 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 54, 0, 0, 100, + 0, 0, 0, 0, 0, 0, 200, 0, 0, false, 54, 0, 0, 100, "thief")); push_back(MonsterStruct("Troll Grunt", 10000, 100, 5, 50, 1, CLASS_16, 2, 25, DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 50, 50, 50, - 50, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 136, "troll")); + 50, 0, 0, 0, 0, 0, 0, 0, false, 56, 0, 0, 136, "troll")); push_back(MonsterStruct("Vampire", 200000, 400, 30, 80, 1, CLASS_CLERIC, 10, 10, DT_PHYSICAL, SA_WEAKEN, 100, 0, MONSTER_UNDEAD, 50, - 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 57, 0, 0, 42, + 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, false, 57, 0, 0, 42, "vamp")); push_back(MonsterStruct("Vampire Lord", 300000, 500, 35, 100, 1, CLASS_CLERIC, 10, 30, DT_PHYSICAL, SA_SLEEP, 120, 0, MONSTER_UNDEAD, - 50, 50, 50, 50, 50, 50, 70, 0, 0, 0, 0, 0, 58, 0, 0, + 50, 50, 50, 50, 50, 50, 70, 0, 0, 0, 0, false, 58, 0, 0, 42, "vamp")); push_back(MonsterStruct("Vulture Roc", 200000, 2500, 50, 150, 1, CLASS_16, 5, 60, DT_PHYSICAL, SA_NONE, 100, 0, MONSTER_ANIMAL, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 59, 0, 0, 120, "vulture")); + 0, 0, 0, 0, 0, 0, 0, 0, 0, true, 59, 0, 0, 120, "vulture")); push_back(MonsterStruct("Sewer Hag", 50000, 75, 10, 40, 1, CLASS_PALADIN, 10, 25, DT_ELECTRICAL, SA_INSANE, 1, 1, MONSTER_HUMANOID, - 0, 100, 0, 100, 0, 20, 0, 0, 0, 10, 0, 0, 62, 0, 0, + 0, 100, 0, 100, 0, 20, 0, 0, 0, 10, 0, false, 62, 0, 0, 108, "elecspel")); push_back(MonsterStruct("Tidal Terror", 500000, 1000, 10, 200, 1, CLASS_15, 5, 100, DT_COLD, SA_NONE, 1, 0, MONSTER_0, 100, 50, 50, - 100, 50, 0, 100, 0, 0, 0, 0, 1, 61, 0, 0, 101, + 100, 50, 0, 100, 0, 0, 0, 0, true, 61, 0, 0, 101, "splash3")); push_back(MonsterStruct("Witch", 80000, 150, 15, 70, 1, CLASS_15, 10, 10, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, 0, 100, - 0, 20, 0, 20, 0, 0, 0, 10, 0, 0, 63, 0, 0, 114, + 0, 20, 0, 20, 0, 0, 0, 10, 0, false, 63, 0, 0, 114, "elecspel")); push_back(MonsterStruct("Coven Leader", 120000, 250, 20, 100, 1, CLASS_15, 10, 15, DT_ENERGY, SA_DRAINSP, 1, 1, MONSTER_HUMANOID, 10, - 100, 0, 50, 100, 50, 0, 0, 0, 20, 6, 0, 63, 0, 10, 114, + 100, 0, 50, 100, 50, 0, 0, 0, 20, 6, false, 63, 0, 10, 114, "elecspel")); push_back(MonsterStruct("Master Wizard", 120000, 500, 25, 150, 2, CLASS_KNIGHT, 10, 40, DT_FIRE, SA_NONE, 1, 1, MONSTER_HUMANOID, 100, - 50, 50, 50, 50, 50, 0, 0, 0, 50, 0, 0, 64, 0, 0, 163, + 50, 50, 50, 50, 50, 0, 0, 0, 50, 0, false, 64, 0, 0, 163, "boltelec")); push_back(MonsterStruct("Wizard", 60000, 250, 20, 125, 1, CLASS_PALADIN, 10, 25, DT_1, SA_NONE, 1, 1, MONSTER_HUMANOID, 50, 30, 30, - 30, 30, 30, 0, 0, 0, 20, 0, 0, 65, 0, 0, 163, "wizard")); + 30, 30, 30, 0, 0, 0, 20, 0, false, 65, 0, 0, 163, "wizard")); push_back(MonsterStruct("Dark Wolf", 10000, 70, 10, 70, 3, CLASS_16, 3, 8, DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_ANIMAL, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 1, 0, 100, "wolf")); + 0, 0, 0, 0, 0, 0, 0, 0, false, 66, 1, 0, 100, "wolf")); push_back(MonsterStruct("Screamer", 500000, 3000, 50, 200, 1, CLASS_15, 10, 20, DT_POISON, SA_POISON, 1, 0, MONSTER_0, 0, 0, 0, 100, 0, - 0, 60, 0, 0, 0, 0, 0, 67, 0, 0, 110, "dragon")); + 0, 60, 0, 0, 0, 0, false, 67, 0, 0, 110, "dragon")); push_back(MonsterStruct("Cult Leader", 100000, 100, 20, 60, 1, CLASS_15, 10, 10, DT_ENERGY, SA_NONE, 1, 1, MONSTER_HUMANOID, 50, 50, - 50, 50, 100, 50, 0, 0, 0, 100, 6, 0, 8, 0, 0, 100, + 50, 50, 100, 50, 0, 0, 0, 100, 6, false, 8, 0, 0, 100, "cleric")); push_back(MonsterStruct("Mega Dragon", 100000000, 64000, 100, 200, 1, CLASS_15, 10, 200, DT_ENERGY, SA_ERADICATE, 1, 1, MONSTER_DRAGON, - 100, 100, 100, 100, 100, 100, 90, 0, 0, 232, 0, 0, 11, + 100, 100, 100, 100, 100, 100, 90, 0, 0, 232, 0, false, 11, 0, 7, 100, "tiger1")); push_back(MonsterStruct("Gettlewaithe", 5000, 100, 15, 35, 2, CLASS_16, 5, 5, DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_0, 0, 0, 0, 0, 0, - 0, 0, 0, 2000, 0, 5, 0, 25, 0, 0, 100, "gremlin")); + 0, 0, 0, 2000, 0, 5, false, 25, 0, 0, 100, "gremlin")); push_back(MonsterStruct("Doom Knight", 500000, 1000, 50, 100, 4, CLASS_PALADIN, 2, 250, DT_PHYSICAL, SA_DEATH, 150, 0, MONSTER_HUMANOID, 80, 80, 80, 80, 80, 20, 0, 0, 200, - 0, 7, 0, 30, 0, 10, 100, "knight")); + 0, 7, false, 30, 0, 10, 100, "knight")); push_back(MonsterStruct("Sandro", 200000, 1000, 20, 75, 1, CLASS_15, 10, 10, DT_1, SA_DEATH, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0, 0, - 90, 80, 0, 0, 100, 7, 1, 34, 0, 10, 100, "lich")); + 90, 80, 0, 0, 100, 7, true, 34, 0, 10, 100, "lich")); push_back(MonsterStruct("Mega Mage", 500000, 500, 35, 100, 1, CLASS_15, 10, 40, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_0, 80, 100, 80, - 80, 80, 80, 0, 0, 0, 100, 6, 1, 35, 0, 11, 100, + 80, 80, 80, 0, 0, 0, 100, 6, true, 35, 0, 11, 100, "monsterb")); push_back(MonsterStruct("Orc Elite", 15000, 200, 15, 40, 2, CLASS_12, 5, 10, DT_PHYSICAL, SA_NONE, 20, 0, MONSTER_HUMANOID, 0, 0, - 0, 0, 0, 0, 0, 0, 100, 0, 3, 0, 40, 0, 0, 100, "orc")); + 0, 0, 0, 0, 0, 0, 100, 0, 3, false, 40, 0, 0, 100, "orc")); push_back(MonsterStruct("Shaalth", 20000, 300, 15, 50, 1, CLASS_15, 5, 10, DT_COLD, SA_SLEEP, 1, 0, MONSTER_HUMANOID, 0, 0, 0, 0, - 0, 20, 0, 0, 1000, 50, 5, 0, 43, 0, 10, 100, "fx7")); + 0, 20, 0, 0, 1000, 50, 5, false, 43, 0, 10, 100, "fx7")); push_back(MonsterStruct("Rooka", 5000, 60, 5, 40, 1, CLASS_16, 3, 10, DT_PHYSICAL, SA_DISEASE, 15, 0, MONSTER_ANIMAL, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 10, 4, 0, 47, 0, 0, 100, "rat")); + 0, 0, 0, 0, 0, 0, 0, 10, 4, false, 47, 0, 0, 100, "rat")); push_back(MonsterStruct("Morgana", 200000, 300, 35, 100, 1, CLASS_15, 2, 60, DT_ENERGY, SA_PARALYZE, 1, 1, MONSTER_HUMANOID, 50, 50, - 50, 50, 100, 80, 0, 0, 0, 100, 6, 0, 50, 0, 10, 100, + 50, 50, 100, 80, 0, 0, 0, 100, 6, false, 50, 0, 10, 100, "disint")); push_back(MonsterStruct("Master Thief", 20000, 100, 20, 50, 1, CLASS_ROBBER, 1, 250, DT_PHYSICAL, SA_NONE, 40, 0, MONSTER_HUMANOID, 0, - 0, 0, 0, 0, 0, 0, 0, 250, 20, 4, 0, 54, 0, 14, 100, + 0, 0, 0, 0, 0, 0, 0, 250, 20, 4, false, 54, 0, 14, 100, "thief")); push_back(MonsterStruct("Royal Vampire", 400000, 750, 40, 125, 1, CLASS_CLERIC, 10, 50, DT_PHYSICAL, SA_CURSEITEM, 120, 0, MONSTER_UNDEAD, 50, 50, 50, 50, 50, 50, 65, 0, 0, 0, 0, - 0, 57, 0, 0, 100, "vamp")); + false, 57, 0, 0, 100, "vamp")); push_back(MonsterStruct("Ct. Blackfang", 2000000, 1500, 50, 150, 1, CLASS_CLERIC, 10, 100, DT_PHYSICAL, SA_DEATH, 120, 0, MONSTER_UNDEAD, 75, 75, 75, 75, 75, 75, 75, 0, 0, 0, 0, - 0, 58, 0, 10, 100, "vamp")); + false, 58, 0, 10, 100, "vamp")); push_back(MonsterStruct("Troll Guard", 15000, 200, 10, 60, 1, CLASS_16, 2, 35, DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 50, 50, 50, - 50, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 100, "troll")); + 50, 0, 0, 0, 0, 0, 0, 0, false, 56, 0, 0, 100, "troll")); push_back(MonsterStruct("Troll Chief", 20000, 300, 15, 65, 1, CLASS_16, 2, 50, DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 50, 50, 50, - 50, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 100, "troll")); + 50, 0, 0, 0, 0, 0, 0, 0, false, 56, 0, 0, 100, "troll")); push_back(MonsterStruct("Hobstadt", 25000, 400, 20, 70, 1, CLASS_16, 2, 50, DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 50, 50, 50, - 50, 0, 0, 0, 0, 1000, 0, 4, 0, 56, 0, 0, 100, "troll")); + 50, 0, 0, 0, 0, 1000, 0, 4, false, 56, 0, 0, 100, "troll")); push_back(MonsterStruct("Graalg", 20000, 200, 15, 50, 1, CLASS_16, 5, 10, DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 0, 0, 0, 0, 0, - 0, 0, 0, 1000, 0, 5, 0, 42, 0, 0, 100, "ogre")); + 0, 0, 0, 1000, 0, 5, false, 42, 0, 0, 100, "ogre")); push_back(MonsterStruct("Vampire King", 3000000, 10000, 60, 200, 1, CLASS_CLERIC, 10, 250, DT_PHYSICAL, SA_ERADICATE, 150, 0, MONSTER_UNDEAD, 80, 80, 80, 80, 80, 80, 90, 0, 0, 0, - 0, 0, 58, 0, 0, 100, "vamp")); + 0, false, 58, 0, 0, 100, "vamp")); push_back(MonsterStruct("Valio", 60000, 150, 15, 60, 1, CLASS_PALADIN, 10, 25, DT_1, SA_NONE, 1, 0, MONSTER_HUMANOID, 50, 30, 30, 30, - 40, 30, 0, 0, 0, 0, 0, 0, 65, 0, 0, 100, "wizard")); + 40, 30, 0, 0, 0, 0, 0, false, 65, 0, 0, 100, "wizard")); push_back(MonsterStruct("Sky Golem", 200000, 1000, 50, 100, 1, CLASS_15, 2, 100, DT_COLD, SA_NONE, 1, 1, MONSTER_GOLEM, 50, 50, - 100, 50, 50, 50, 50, 0, 0, 0, 0, 1, 24, 0, 0, 100, + 100, 50, 50, 50, 50, 0, 0, 0, 0, true, 24, 0, 0, 100, "golem")); push_back(MonsterStruct("Gurodel", 100000, 750, 30, 60, 2, CLASS_16, 100, 6, DT_PHYSICAL, SA_UNCONSCIOUS, 110, 0, MONSTER_0, 0, 0, - 0, 0, 0, 0, 0, 0, 5000, 0, 6, 0, 22, 0, 0, 100, + 0, 0, 0, 0, 0, 0, 5000, 0, 6, false, 22, 0, 0, 100, "giant")); push_back(MonsterStruct("Yog", 25000, 100, 5, 60, 1, CLASS_SORCERER, 1, 30, DT_PHYSICAL, SA_NONE, 25, 0, MONSTER_HUMANOID, 0, 0, - 0, 0, 0, 0, 0, 0, 200, 0, 4, 0, 6, 0, 10, 100, + 0, 0, 0, 0, 0, 0, 200, 0, 4, false, 6, 0, 10, 100, "barbarch")); push_back(MonsterStruct("Sharla", 10000, 50, 5, 50, 1, CLASS_RANGER, 3, 4, DT_PHYSICAL, SA_NONE, 20, 0, MONSTER_0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 53, 0, 0, 100, "hiss")); + 0, 0, 0, 0, 0, 0, true, 53, 0, 0, 100, "hiss")); push_back(MonsterStruct("Ghost Mummy", 500000, 500, 35, 175, 1, CLASS_CLERIC, 200, 5, DT_PHYSICAL, SA_AGING, 150, 0, MONSTER_UNDEAD, - 0, 60, 80, 80, 80, 50, 80, 0, 0, 0, 0, 0, 40, 0, 6, + 0, 60, 80, 80, 80, 50, 80, 0, 0, 0, 0, false, 40, 0, 6, 100, "orc")); push_back(MonsterStruct("Phase Mummy", 500000, 500, 35, 175, 1, CLASS_CLERIC, 200, 6, DT_PHYSICAL, SA_DRAINSP, 150, 0, MONSTER_UNDEAD, 0, 70, 80, 80, 80, 60, 85, 0, 0, 0, 0, - 0, 39, 0, 7, 100, "mummy")); + false, 39, 0, 7, 100, "mummy")); push_back(MonsterStruct("Xenoc", 250000, 700, 35, 175, 1, CLASS_15, 10, 50, DT_ENERGY, SA_NONE, 1, 0, MONSTER_HUMANOID, 50, 50, 50, - 50, 100, 50, 0, 0, 0, 100, 6, 0, 64, 0, 0, 100, + 50, 100, 50, 0, 0, 0, 100, 6, false, 64, 0, 0, 100, "boltelec")); push_back(MonsterStruct("Barkman", 4000000, 40000, 25, 100, 3, CLASS_16, 250, 1, DT_FIRE, SA_NONE, 1, 0, MONSTER_0, 100, 50, 0, 100, - 0, 0, 0, 0, 0, 0, 6, 0, 19, 0, 11, 100, "fire")); + 0, 0, 0, 0, 0, 0, 6, false, 19, 0, 11, 100, "fire")); } void MonsterData::load(const Common::String &name) { diff --git a/engines/xeen/map.h b/engines/xeen/map.h index ec9604c849..3ade915d4b 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -104,7 +104,7 @@ public: int fireResistence, int electricityResistence, int coldResistence, int poisonResistence, int energyResistence, int magicResistence, int phsyicalResistence, int field29, int gold, int gems, int itemDrop, - int flying, int imageNumber, int loopAnimation, int animationEffect, + bool flying, int imageNumber, int loopAnimation, int animationEffect, int field32, Common::String attackVoc); void synchronize(Common::SeekableReadStream &s); -- cgit v1.2.3 From 07a10855be2f60ae253623c26c8bb0ac38e58af4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 18 Jan 2015 19:12:10 -0500 Subject: XEEN: In progress work on sprite scaling --- engines/xeen/screen.cpp | 2 +- engines/xeen/sprites.cpp | 34 +++++++++++-- engines/xeen/sprites.h | 3 +- engines/xeen/xsurface.cpp | 121 ++++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/xsurface.h | 3 ++ 5 files changed, 156 insertions(+), 7 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index b1b42ac551..de591d396d 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -178,7 +178,7 @@ void Window::drawList(DrawStruct *items, int count) { // TODO: There are two sprite calls in this method. Figure out why items->_sprites->draw(screen, items->_frame, - Common::Point(items->_x, items->_y), items->_flags); + Common::Point(items->_x, items->_y), items->_flags, items->_scale); } } diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 8a14ec0178..8ddf4ed48d 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -228,11 +228,35 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi dest.addDirtyRect(r); } -void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, int flags) const { - // TODO: Support the different flags - drawOffset(dest, _index[frame]._offset1, destPos, flags); - if (_index[frame]._offset2) - drawOffset(dest, _index[frame]._offset2, destPos, flags); +void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, + int flags, int scale) const { + if (scale == 0) { + drawOffset(dest, _index[frame]._offset1, destPos, flags); + if (_index[frame]._offset2) + drawOffset(dest, _index[frame]._offset2, destPos, flags); + } else { + // Get the bounds for the surface and create a temporary one + Common::MemoryReadStream f(_data, _filesize); + f.seek(_index[frame]._offset1); + int xOffset = f.readUint16LE(); + int width = f.readUint16LE(); + int yOffset = f.readUint16LE(); + int height = f.readUint16LE(); + XSurface tempSurface(xOffset + width, yOffset + height); + + // Draw sprite into temporary surface + tempSurface.fillRect(Common::Rect(0, 0, width, height), 0); + drawOffset(tempSurface, _index[frame]._offset1, Common::Point(), flags); + if (_index[frame]._offset2) + drawOffset(tempSurface, _index[frame]._offset2, Common::Point(), flags); + + // TODO: I don't currently know the algorithm the original used for scaling. + // This is a best fit estimate that every increment of the scale field + // reduces the size of a sprite by approximately 6.6% + int newScale = MAX(100.0 - 6.6 * scale, 0.0); + if (newScale > 0) + tempSurface.transBlitTo(dest, Common::Point(), newScale, 0); + } } void SpriteResource::draw(XSurface &dest, int frame) const { diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index 973875cfed..d1a801e6ca 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -62,7 +62,8 @@ public: void clear(); - void draw(XSurface &dest, int frame, const Common::Point &destPos, int flags = 0) const; + void draw(XSurface &dest, int frame, const Common::Point &destPos, + int flags = 0, int scale = 0) const; void draw(XSurface &dest, int frame) const; diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp index 698e478aee..b01ade17df 100644 --- a/engines/xeen/xsurface.cpp +++ b/engines/xeen/xsurface.cpp @@ -24,6 +24,7 @@ #include "common/util.h" #include "xeen/xsurface.h" #include "xeen/resources.h" +#include "xeen/screen.h" namespace Xeen { @@ -80,6 +81,126 @@ void XSurface::transBlitTo(XSurface &dest, const Common::Point &destPos) const { dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y)); } +void XSurface::transBlitTo(XSurface &dest, const Common::Point &destPos, + int scale, int transparentColor) { + int destX = destPos.x, destY = destPos.y; + int frameWidth = this->w; + int frameHeight = this->h; + int direction = 1; + + int highestDim = MAX(frameWidth, frameHeight); + bool lineDist[SCREEN_WIDTH]; + int distXCount = 0, distYCount = 0; + + if (scale != 0) { + int distCtr = 0; + int distIndex = 0; + do { + distCtr += scale; + if (distCtr < 100) { + lineDist[distIndex] = false; + } + else { + lineDist[distIndex] = true; + distCtr -= 100; + + if (distIndex < frameWidth) + ++distXCount; + + if (distIndex < frameHeight) + ++distYCount; + } + } while (++distIndex < highestDim); + + destX -= distXCount / 2; + destY -= distYCount - 1; + } + + // Start of draw logic for scaled sprites + const byte *srcPixelsP = (const byte *)getPixels(); + + int destRight = dest.w - 1; + int destBottom = dest.h - 1; + + // Check x bounding area + int spriteLeft = 0; + int spriteWidth = distXCount; + int widthAmount = destX + distXCount - 1; + + if (destX < 0) { + spriteWidth += destX; + spriteLeft -= destX; + } + widthAmount -= destRight; + if (widthAmount > 0) + spriteWidth -= widthAmount; + + if (spriteWidth <= 0) + return; + + // Check y bounding area + int spriteTop = 0; + int spriteHeight = distYCount; + int heightAmount = destY + distYCount - 1; + + if (destY < 0) { + spriteHeight += destY; + spriteTop -= destY; + } + heightAmount -= destBottom; + if (heightAmount > 0) + spriteHeight -= heightAmount; + int spriteBottom = spriteTop + spriteHeight; + + if (spriteHeight <= 0) + return; + + byte *destPixelsP = (byte *)dest.getBasePtr(destX + spriteLeft, destY + spriteTop); + int destWidth = 0, destHeight = 0; + + spriteLeft = spriteLeft * direction; + + // Loop through the lines of the sprite + for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += this->pitch) { + if (!lineDist[yp]) + // Not a display line, so skip it + continue; + // Check whether the sprite line is in the display range + ++sprY; + if ((sprY >= spriteBottom) || (sprY < spriteTop)) + continue; + + // Found a line to display. Loop through the pixels + const byte *srcP = srcPixelsP; + byte *destP = destPixelsP; + ++destHeight; + + for (int xp = 0, sprX = 0; xp < frameWidth; ++xp, ++srcP) { + if (xp < spriteLeft) + // Not yet reached start of display area + continue; + if (!lineDist[sprX++]) + // Not a display pixel + continue; + + if (*srcP != transparentColor) + *destP = *srcP; + + destP += direction; + } + + // Keep track of widest line drawn + destWidth = MAX(destP - destPixelsP, destWidth); + + // Move to the next destination line + destPixelsP += dest.pitch; + } + + // Add a dirty rect for the affected area + dest.addDirtyRect(Common::Rect(destX + spriteLeft, destY + spriteTop, + destX + spriteLeft + destWidth, destY + spriteTop + destHeight)); +} + void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const { if (dest.getPixels() == nullptr) dest.create(w, h); diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h index 263ea5336f..61f4f96cb1 100644 --- a/engines/xeen/xsurface.h +++ b/engines/xeen/xsurface.h @@ -48,6 +48,9 @@ public: void transBlitTo(XSurface &dest, const Common::Point &destPos) const; + void transBlitTo(XSurface &dest, const Common::Point &destPos, + int scale, int transparentColor); + void blitTo(XSurface &dest, const Common::Point &destPos) const; void blitTo(XSurface &dest) const; -- cgit v1.2.3 From ecdf6412a6d74853ff20cbb7ea5abbdeaa789b63 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 18 Jan 2015 19:18:00 -0500 Subject: XEEN: Fix drawing the game window border --- engines/xeen/interface.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 87259d83bf..8d8b4ab5b9 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -313,10 +313,11 @@ void Interface::assembleBorder() { Window &gameWindow = screen._windows[28]; // Draw the outer frame - _globalSprites.draw(gameWindow, 0); + _globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8)); // Draw the animating bat character used to show when levitate is active - _borderSprites.draw(screen, _vm->_party._levitateActive ? _batUIFrame + 16 : 16); + _borderSprites.draw(screen._windows[0], _vm->_party._levitateActive ? _batUIFrame + 16 : 16, + Common::Point(0, 82)); _batUIFrame = (_batUIFrame + 1) % 12; // Draw UI element to indicate whether can spot hidden doors -- cgit v1.2.3 From e4c473630655bd9b68d925b338559706ea927497 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 18 Jan 2015 20:11:31 -0500 Subject: XEEN: Renaming of flags and surface display --- engines/xeen/interface.cpp | 3 +-- engines/xeen/interface_map.cpp | 23 +++++++++++++---------- engines/xeen/interface_map.h | 7 ++++--- engines/xeen/map.cpp | 5 ++--- engines/xeen/map.h | 5 +++-- engines/xeen/resources.cpp | 2 +- engines/xeen/resources.h | 2 +- 7 files changed, 25 insertions(+), 22 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 8d8b4ab5b9..a2c42a7b40 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -310,7 +310,6 @@ void Interface::setupBackground() { void Interface::assembleBorder() { Screen &screen = *_vm->_screen; - Window &gameWindow = screen._windows[28]; // Draw the outer frame _globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8)); @@ -548,7 +547,7 @@ void Interface::draw3d(bool updateFlag) { _flipUIFrame = (_flipUIFrame + 1) % 4; if (_flipUIFrame == 0) - _flipWtr = !_flipWtr; + _flipWater = !_flipWater; if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_2) && !_flag1 && _vm->_moveMonsters) { if (--_tillMove == 0) diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index d34373ea3d..ddc311bae0 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -181,6 +181,7 @@ IndoorDrawList::IndoorDrawList() : _fwl_3F2R(_data[ 91]), _fwl_3F1R(_data[ 90]), _fwl_3F( _data[ 89]), _fwl_3F1L(_data[ 88]), _fwl_3F2L(_data[ 87]), _fwl_1F( _data[147]), _fwl_1F1R(_data[145]), _fwl_1F1L(_data[143]), + _groundTiles(&_data[3]), _objects0(_data[149]), _objects1(_data[125]), _objects2(_data[126]), _objects3(_data[127]), _objects4(_data[97]), _objects5(_data[98]), _objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]), @@ -364,10 +365,10 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) { Common::fill(&_wp[0], &_wp[20], 0); Common::fill(&_wo[0], &_wo[308], 0); _overallFrame = 0; - _flipWtr = false; - _flipWall = false; - _flipSky = false; + _flipWater = false; _flipGround = false; + _flipSky = false; + _flipDefaultGround = false; _isShooting = false; _charsShooting = false; _objNumber = 0; @@ -1106,20 +1107,22 @@ void InterfaceMap::drawIndoors() { Map &map = *_vm->_map; int surfaceId; + // Draw any surface tiles on top of the default ground for (int cellIndex = 0; cellIndex < 25; ++cellIndex) { map.getCell(DRAW_NUMBERS[cellIndex]); - DrawStruct &drawStruct = _indoorList[3 + cellIndex]; + DrawStruct &drawStruct = _indoorList._groundTiles[cellIndex]; if (!map._surfaceSprites[map._currentSurfaceId].empty()) drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId]; surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; - if (surfaceId == 0 || surfaceId == 5 || surfaceId == 12) { - drawStruct._flags = _flipWtr ? 1 : 0; - drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWtr ? 1 : 0]; + if (surfaceId == SURFTYPE_WATER || surfaceId == SURFTYPE_LAVA || + surfaceId == SURFTYPE_SEWER) { + drawStruct._flags = _flipWater ? 1 : 0; + drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWater ? 1 : 0]; } else { - drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWall ? 1 : 0]; - drawStruct._flags = _flipWall ? SPRFLAG_HORIZ_FLIPPED : 0; + drawStruct._frame = DRAW_FRAMES[cellIndex][_flipGround ? 1 : 0]; + drawStruct._flags = _flipGround ? SPRFLAG_HORIZ_FLIPPED : 0; } } @@ -1932,7 +1935,7 @@ void InterfaceMap::drawIndoors() { } _indoorList._sky._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0; - _indoorList._ground._flags = _flipGround ? SPRFLAG_HORIZ_FLIPPED : 0; + _indoorList._ground._flags = _flipDefaultGround ? SPRFLAG_HORIZ_FLIPPED : 0; _indoorList._horizon._frame = 7; // Finally draw the darn indoor scene diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 2376f8f55b..fd807a03d2 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -53,6 +53,7 @@ public: DrawStruct &_sky; DrawStruct &_ground; DrawStruct &_horizon; + DrawStruct * const _groundTiles; DrawStruct &_swl_0F1R, &_swl_0F1L, &_swl_1F1R, &_swl_1F1L, &_swl_2F2R, &_swl_2F1R, &_swl_2F1L, &_swl_2F2L, &_swl_3F1R, &_swl_3F2R, &_swl_3F3R, &_swl_3F4R, @@ -92,10 +93,10 @@ protected: int8 _wp[20]; byte _wo[308]; int _overallFrame; - bool _flipWtr; - bool _flipWall; - bool _flipSky; + bool _flipWater; bool _flipGround; + bool _flipSky; + bool _flipDefaultGround; bool _isShooting; bool _charsShooting; int _objNumber; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 0623772953..d39b8f5199 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -877,7 +877,6 @@ void Map::load(int mapId) { Screen &screen = *_vm->_screen; IndoorDrawList &indoorList = _vm->_interface->_indoorList; OutdoorDrawList &outdoorList = _vm->_interface->_outdoorList; - int sideNumber = 0; if (_vm->_falling) { Window &w = screen._windows[9]; @@ -1097,7 +1096,7 @@ void Map::load(int mapId) { _surfaceSprites[i].clear(); if (i != 0 && _mazeData[0]._wallTypes[i] != 0) - _surfaceSprites[i].load(OUTDOOR_SURFACES[_mazeData[0]._surfaceTypes[i]]); + _surfaceSprites[i].load(SURFACE_NAMES[_mazeData[0]._surfaceTypes[i]]); } } else { warning("TODO"); // Sound loading @@ -1114,7 +1113,7 @@ void Map::load(int mapId) { _surfaceSprites[i].clear(); if (_mazeData[0]._surfaceTypes[i] != 0 || i == 4) - _surfaceSprites[i].load(OUTDOOR_SURFACES[i]); + _surfaceSprites[i].load(SURFACE_NAMES[i]); } for (int i = 0; i < TOTAL_SURFACES; ++i) diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 3ade915d4b..c97de72a23 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -159,9 +159,10 @@ enum MazeFlags { enum MazeFlags2 { FLAG_IS_OUTDOORS = 0x8000, FLAG_IS_DARK = 0x4000 }; enum SurfaceType { - SURFTYPE_DEFAULT = 0, SURFTYPE_DIRT = 1, SURFTYPE_GRASS = 2, + SURFTYPE_DEFAULT = 0, + SURFTYPE_WATER = 0, SURFTYPE_DIRT = 1, SURFTYPE_GRASS = 2, SURFTYPE_SNOW = 3, SURFTYPE_SWAMP = 4, SURFTYPE_LAVA = 5, - SURFTYPE_DESERT = 6, SURFTYPE_ROAD = 7, SURFTYPE_WATER = 8, + SURFTYPE_DESERT = 6, SURFTYPE_ROAD = 7, SURFTYPE_DWATER = 8, SURFTYPE_TFLR = 9, SURFTYPE_SKY = 10, SURFTYPE_CROAD = 11, SURFTYPE_SEWER = 12, SURFTYPE_CLOUD = 13, SURFTYPE_SCORCH = 14, SURFTYPE_SPACE = 15 diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 21a967dbf1..51f26fe668 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -76,7 +76,7 @@ const char *const SURFACE_TYPE_NAMES[15] = { "dedltree", "dedltree" }; -const char *const OUTDOOR_SURFACES[16] = { +const char *const SURFACE_NAMES[16] = { "water.srf", "dirt.srf", "grass.srf", "snow.srf", "swamp.srf", "lava.srf", "desert.srf", "road.srf", "dwater.srf", "tflr.srf", "sky.srf", "croad.srf", "sewer.srf", "cloud.srf", "scortch.srf", diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 2160d55c53..0ef9211288 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -36,7 +36,7 @@ extern const char *const TERRAIN_TYPES[6]; extern const char *const SURFACE_TYPE_NAMES[15]; -extern const char *const OUTDOOR_SURFACES[16]; +extern const char *const SURFACE_NAMES[16]; extern const byte SYMBOLS[20][64]; -- cgit v1.2.3 From 130bd58e2c8ffdac6de86364d45d772ffe6a8d1b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 18 Jan 2015 20:54:58 -0500 Subject: XEEN: Load correct surface sprites for the maze --- engines/xeen/interface_map.cpp | 2 +- engines/xeen/map.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index ddc311bae0..93c3d9a679 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -1118,8 +1118,8 @@ void InterfaceMap::drawIndoors() { surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; if (surfaceId == SURFTYPE_WATER || surfaceId == SURFTYPE_LAVA || surfaceId == SURFTYPE_SEWER) { - drawStruct._flags = _flipWater ? 1 : 0; drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWater ? 1 : 0]; + drawStruct._flags = _flipWater ? SPRFLAG_HORIZ_FLIPPED : 0; } else { drawStruct._frame = DRAW_FRAMES[cellIndex][_flipGround ? 1 : 0]; drawStruct._flags = _flipGround ? SPRFLAG_HORIZ_FLIPPED : 0; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index d39b8f5199..9c69106857 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1089,13 +1089,14 @@ void Map::load(int mapId) { for (int i = 0; i < TOTAL_SURFACES; ++i) { _wallSprites._surfaces[i].clear(); + if (_mazeData[0]._wallTypes[i] != 0) { _wallSprites._surfaces[i].load(Common::String::format("%s.wal", - SURFACE_TYPE_NAMES[i])); + SURFACE_TYPE_NAMES[_mazeData[0]._wallTypes[i]])); } _surfaceSprites[i].clear(); - if (i != 0 && _mazeData[0]._wallTypes[i] != 0) + if (i != 0 && _mazeData[0]._surfaceTypes[i] != 0) _surfaceSprites[i].load(SURFACE_NAMES[_mazeData[0]._surfaceTypes[i]]); } } else { @@ -1113,7 +1114,7 @@ void Map::load(int mapId) { _surfaceSprites[i].clear(); if (_mazeData[0]._surfaceTypes[i] != 0 || i == 4) - _surfaceSprites[i].load(SURFACE_NAMES[i]); + _surfaceSprites[i].load(SURFACE_NAMES[_mazeData[0]._surfaceTypes[i]]); } for (int i = 0; i < TOTAL_SURFACES; ++i) -- cgit v1.2.3 From b12e26836aacfd414abb5967f7475435a4fd55a5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 18 Jan 2015 20:56:35 -0500 Subject: XEEN: Disable initial fade out for now --- engines/xeen/xeen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index b3758b57ed..6b73de6939 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -291,7 +291,7 @@ void XeenEngine::play() { _interface->startup(); if (_mode == MODE_0) { - _screen->fadeOut(4); +// _screen->fadeOut(4); } _screen->_windows[0].update(); -- cgit v1.2.3 From f46b9d77dd1427aacb095f834f10f3fb45502637 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 19 Jan 2015 10:28:48 -0500 Subject: XEEN: Compilation fixes for gcc --- engines/xeen/darkside/darkside_game.cpp | 13 +++++++------ engines/xeen/dialogs.cpp | 4 ++-- engines/xeen/dialogs.h | 2 ++ engines/xeen/dialogs_error.cpp | 2 +- engines/xeen/dialogs_options.h | 8 ++++++++ engines/xeen/font.cpp | 22 +++++++++++----------- engines/xeen/font.h | 2 +- engines/xeen/interface.cpp | 6 +++--- engines/xeen/module.mk | 1 - engines/xeen/sound.cpp | 2 +- engines/xeen/sound.h | 4 ++-- 11 files changed, 38 insertions(+), 28 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp index 60cb69362a..fe8c161287 100644 --- a/engines/xeen/darkside/darkside_game.cpp +++ b/engines/xeen/darkside/darkside_game.cpp @@ -66,9 +66,10 @@ void DarkSideEngine::showTitle1() { SpriteResource("nwc1.int"), SpriteResource("nwc2.int"), SpriteResource("nwc3.int"), SpriteResource("nwc4.int") }; - File voc[3] = { - File("dragon1.voc"), File("dragon2.voc"), File("dragon3.voc") - }; + Common::File voc[3]; + voc[0].open("dragon1.voc"); + voc[1].open("dragon2.voc"); + voc[2].open("dragon3.voc"); // Load backgrounds _screen->loadBackground("nwc1.raw"); @@ -168,9 +169,9 @@ void DarkSideEngine::showStartSequence() { SpriteResource sprites[3] = { SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int") }; - File voc[2] = { - File("pharoh1a.voc"), File("pharoh1b.voc") - }; + Common::File voc[2]; + voc[0].open("pharoh1a.voc"); + voc[1].open("pharoh1b.voc"); _screen->vertMerge(SCREEN_HEIGHT); _screen->loadPage(0); diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index c677fc8efb..824e8249ce 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -102,14 +102,14 @@ void ButtonContainer::doScroll(XeenEngine *vm, bool drawFlag, bool doFade) { // Load hand vga files SpriteResource *hand[16]; for (int i = 0; i < 16; ++i) { - Common::String name = Common::String::format("hand%02u.vga", i); + Common::String name = Common::String::format("hand%02d.vga", i); hand[i] = new SpriteResource(name); } // Load marb vga files SpriteResource *marb[5]; for (int i = 1; i < 5; ++i) { - Common::String name = Common::String::format("marb%02u.vga"); + Common::String name = Common::String::format("marb%02d.vga", i); marb[i] = new SpriteResource(name); } diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h index 229c40a2da..d8a9123c10 100644 --- a/engines/xeen/dialogs.h +++ b/engines/xeen/dialogs.h @@ -76,6 +76,8 @@ protected: virtual void showContents(SpriteResource &title1, bool mode); public: SettingsBaseDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + virtual ~SettingsBaseDialog() {} }; class CreditsScreen: public ButtonContainer { diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp index c0c072386d..e8512216c7 100644 --- a/engines/xeen/dialogs_error.cpp +++ b/engines/xeen/dialogs_error.cpp @@ -38,7 +38,7 @@ void ErrorScroll::execute(const Common::String &msg, ErrorWaitType waitType) { EventsManager &events = *_vm->_events; Window &w = screen._windows[6]; - Common::String s = Common::String::format("\x03c\v010\t000%s", msg); + Common::String s = Common::String::format("\x03c\v010\t000%s", msg.c_str()); w.open(); w.writeString(s); w.update(); diff --git a/engines/xeen/dialogs_options.h b/engines/xeen/dialogs_options.h index 7a933fdea6..bb4aea9a36 100644 --- a/engines/xeen/dialogs_options.h +++ b/engines/xeen/dialogs_options.h @@ -46,6 +46,8 @@ protected: virtual void openWindow() {} public: + virtual ~OptionsMenu() {} + static void show(XeenEngine *vm); }; @@ -54,6 +56,8 @@ protected: virtual void startup(Common::String &title1, Common::String &title2); public: CloudsOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {} + + virtual ~CloudsOptionsMenu() {} }; class DarkSideOptionsMenu : public OptionsMenu { @@ -61,6 +65,8 @@ protected: virtual void startup(Common::String &title1, Common::String &title2); public: DarkSideOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {} + + virtual ~DarkSideOptionsMenu() {} }; class WorldOptionsMenu : public DarkSideOptionsMenu { @@ -80,6 +86,8 @@ protected: virtual void showContents(SpriteResource &title1, bool mode); public: WorldOptionsMenu(XeenEngine *vm) : DarkSideOptionsMenu(vm), _bgFrame(0) {} + + virtual ~WorldOptionsMenu() {} }; } // End of namespace Xeen diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp index b5608d48b8..aee05f9066 100644 --- a/engines/xeen/font.cpp +++ b/engines/xeen/font.cpp @@ -34,7 +34,7 @@ FontSurface::FontSurface() : XSurface(), _fontData(nullptr), _bgColor(DEFAULT_BG _textColors[3] = 0x20; } -FontSurface::FontSurface(int w, int h) : XSurface(), _fontData(nullptr), _msgWraps(false), +FontSurface::FontSurface(int wv, int hv) : XSurface(wv, hv), _fontData(nullptr), _msgWraps(false), _bgColor(DEFAULT_BG_COLOR), _fontReduced(false), _fontJustify(JUSTIFY_NONE) { create(w, h); _textColors[0] = 0; @@ -173,12 +173,12 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R _fontJustify = JUSTIFY_NONE; } else if (c == 4) { // Draw an empty box of a given width - int w = fontAtoi(); + int wv = fontAtoi(); Common::Point pt = _writePos; if (_fontJustify == JUSTIFY_RIGHT) - pt.x -= w; + pt.x -= wv; - Common::Rect r(pt.x, pt.y, pt.x + w, pt.y + (_fontReduced ? 9 : 10)); + Common::Rect r(pt.x, pt.y, pt.x + wv, pt.y + (_fontReduced ? 9 : 10)); fillRect(r, _bgColor); } else if (c == 5) { continue; @@ -187,8 +187,8 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R writeChar(' '); } else if (c == 7) { // Set text background color - int c = fontAtoi(); - _bgColor = (c < 0 || c > 255) ? DEFAULT_BG_COLOR : c; + int bgColor = fontAtoi(); + _bgColor = (bgColor < 0 || bgColor > 255) ? DEFAULT_BG_COLOR : bgColor; } else if (c == 8) { // Draw a character outline c = getNextChar(); @@ -218,8 +218,8 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R } } else if (c == 9) { // Skip x position - int xp = fontAtoi(); - _writePos.x = MIN(bounds.left + xp, (int)bounds.right); + int xAmount = fontAtoi(); + _writePos.x = MIN(bounds.left + xAmount, (int)bounds.right); } else if (c == 10) { // Newline if (newLine(bounds)) @@ -304,10 +304,10 @@ bool FontSurface::newLine(const Common::Rect &bounds) { _msgWraps = false; _writePos.x = bounds.left; - int h = _fontReduced ? 9 : 10; - _writePos.y += h; + int hv = _fontReduced ? 9 : 10; + _writePos.y += hv; - return ((_writePos.y + h - 1) > bounds.bottom); + return ((_writePos.y + hv - 1) > bounds.bottom); } /** diff --git a/engines/xeen/font.h b/engines/xeen/font.h index 0f53d5e6a7..6b362d7bf5 100644 --- a/engines/xeen/font.h +++ b/engines/xeen/font.h @@ -58,7 +58,7 @@ public: Justify _fontJustify; public: FontSurface(); - FontSurface(int w, int h); + FontSurface(int wv, int hv); virtual ~FontSurface() {} void writeSymbol(int symbolId); diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index a2c42a7b40..50f3ede109 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -28,7 +28,7 @@ namespace Xeen { Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(vm) { - Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr); + Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], (SpriteResource *)nullptr); _batUIFrame = 0; _spotDoorsUIFrame = 0; _dangerSenseUIFrame = 0; @@ -425,7 +425,7 @@ void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool int charId; for (posIndex = 0; posIndex < 4; ++posIndex) { - int charId = xeenSideChars[charIndex]; + charId = xeenSideChars[charIndex]; bool isInParty = _vm->_party.isInParty(charId); if (charId == 0xff) { @@ -902,7 +902,7 @@ void Interface::setMazeBits() { break; case 4: case 7: - _wo[27]; + ++_wo[27]; break; case 5: ++_wo[227]; diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index d6b8097386..6362ffe1bf 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -18,7 +18,6 @@ MODULE_OBJS := \ items.o \ map.o \ party.o \ - resdata.o \ resources.o \ saves.o \ screen.o \ diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp index 9495b25fe4..7c7524af54 100644 --- a/engines/xeen/sound.cpp +++ b/engines/xeen/sound.cpp @@ -27,7 +27,7 @@ namespace Xeen { SoundManager::SoundManager(XeenEngine *vm): _vm(vm) { } -void SoundManager::proc2(File &f) { +void SoundManager::proc2(Common::SeekableReadStream &f) { } diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index da6548b07d..553b1c6f44 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -35,11 +35,11 @@ private: public: SoundManager(XeenEngine *vm); - void proc2(File &f); + void proc2(Common::SeekableReadStream &f); void startMusic(int v1); - void playSong(const File &f) {} + void playSong(Common::SeekableReadStream &f) {} void playSample(const Common::SeekableReadStream *stream, int v2) {} }; -- cgit v1.2.3 From 83442b9586e3992ab8ee0f0d06e534781f9b448b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 19 Jan 2015 10:51:05 -0500 Subject: XEEN: Fix Valgrind warnings --- engines/xeen/files.cpp | 2 +- engines/xeen/map.cpp | 14 +++++++------- engines/xeen/sprites.cpp | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index f15a08b184..f8e7a3fc0c 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -175,7 +175,7 @@ Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::S // Read in the data for the specific resource f.seek(ccEntry._offset); - byte *data = new byte[ccEntry._size]; + byte *data = (byte *)malloc(ccEntry._size); f.read(data, ccEntry._size); if (_encoded) { diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 9c69106857..99fe5ada0b 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -954,28 +954,28 @@ void Map::load(int mapId) { // Iterate through loading the given maze as well as the two successive // mazes in each of the four cardinal directions bool isDarkCc = _vm->getGameID() == GType_DarkSide; - MazeData *mazeData = &_mazeData[0]; + MazeData *mazeDataP = &_mazeData[0]; bool textLoaded = false; - for (int idx = 0; idx < 9; ++idx, ++mazeData) { - mazeData->_mazeId = mapId; + for (int idx = 0; idx < 9; ++idx, ++mazeDataP) { + mazeDataP->_mazeId = mapId; if (mapId != 0) { // Load in the maze's data file Common::String datName = Common::String::format("maze%c%03d.dat", (mapId >= 100) ? 'x' : '0', mapId); File datFile(datName); - mazeData->synchronize(datFile); + mazeDataP->synchronize(datFile); datFile.close(); if (isDarkCc && mapId == 50) - mazeData->setAllTilesStepped(); + mazeDataP->setAllTilesStepped(); if (!isDarkCc && _vm->_party._gameFlags[25] && (mapId == 42 || mapId == 43 || mapId == 4)) { - mazeData->clearCellSurfaces(); + mazeDataP->clearCellSurfaces(); } - _isOutdoors = (mazeData->_mazeFlags2 & FLAG_IS_OUTDOORS) != 0; + _isOutdoors = (mazeDataP->_mazeFlags2 & FLAG_IS_OUTDOORS) != 0; // Handle loading text data if (!textLoaded) { diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 8ddf4ed48d..448ec0ec57 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -120,7 +120,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi if (lineLength == 0) { // Skip the specified number of scan lines yPos += f.readByte(); - } else if ((destPos.y + yPos) < 0) { + } else if ((destPos.y + yPos) < 0 || (destPos.y + yPos) >= dest.h) { // Skip over the bytes of the line f.skip(lineLength); } else { -- cgit v1.2.3 From 687423b3612d61a18a9854010af56f7a98e5563d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 19 Jan 2015 11:32:57 -0500 Subject: XEEN: Beginnings of main game loop and waiting --- engines/xeen/interface.cpp | 180 +++++++++++++++++++++++++++--------- engines/xeen/interface.h | 10 +- engines/xeen/interface_map.cpp | 32 +++---- engines/xeen/interface_map.h | 2 +- engines/xeen/map.cpp | 47 ++++++---- engines/xeen/map.h | 3 +- engines/xeen/party.cpp | 205 ++++++++++++++++++++++++++++++++++++++++- engines/xeen/party.h | 18 +++- engines/xeen/resources.cpp | 52 ++++------- engines/xeen/resources.h | 4 +- engines/xeen/scripts.cpp | 17 ++++ engines/xeen/scripts.h | 15 +++ engines/xeen/sprites.cpp | 1 + engines/xeen/xeen.cpp | 33 +++++-- engines/xeen/xeen.h | 6 +- 15 files changed, 499 insertions(+), 126 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 50f3ede109..e15c0574aa 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -39,7 +39,6 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm( _holyBonusUIFrame = 0; _heroismUIFrame = 0; _flipUIFrame = 0; - _newDay = false; _buttonsLoaded = false; _hiliteChar = -1; _intrIndex1 = 0; @@ -49,6 +48,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm( _tillMove = 0; _thinWall = false; _overallFrame = 0; + _upDoorText = false; Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); initDrawStructs(); @@ -91,12 +91,12 @@ void Interface::setup() { _charPowSprites.load("charpow.icn"); // Get mappings to the active characters in the party - _vm->_party._activeParty.resize(_vm->_party._partyCount); - for (int i = 0; i < _vm->_party._partyCount; ++i) { - _vm->_party._activeParty[i] = _vm->_roster[_vm->_party._partyMembers[i]]; + _vm->_party->_activeParty.resize(_vm->_party->_partyCount); + for (int i = 0; i < _vm->_party->_partyCount; ++i) { + _vm->_party->_activeParty[i] = _vm->_roster[_vm->_party->_partyMembers[i]]; } - _newDay = _vm->_party._minutes >= 300; + _vm->_party->_newDay = _vm->_party->_minutes >= 300; } void Interface::manageCharacters(bool soundPlayed) { @@ -105,7 +105,7 @@ void Interface::manageCharacters(bool soundPlayed) { bool flag = false; start: - if (_vm->_party._mazeId != 0) { + if (_vm->_party->_mazeId != 0) { _vm->_mode = MODE_0; _buttonsLoaded = true; } else { @@ -117,8 +117,8 @@ start: // Xeen only uses 24 of possible 30 character slots loadCharIcons(); - for (int i = 0; i < _vm->_party._partyCount; ++i) - _partyFaces[i] = &_charFaces[_vm->_party._partyMembers[i]]; + for (int i = 0; i < _vm->_party->_partyCount; ++i) + _partyFaces[i] = &_charFaces[_vm->_party->_partyMembers[i]]; } _vm->_mode = MODE_1; @@ -193,7 +193,7 @@ start: case Common::KEYCODE_SPACE: case Common::KEYCODE_e: case Common::KEYCODE_x: - if (_vm->_party._partyCount == 0) { + if (_vm->_party->_partyCount == 0) { ErrorScroll::show(_vm, NO_ONE_TO_ADVENTURE_WITH); } else { if (_vm->_mode != MODE_0) { @@ -208,10 +208,10 @@ start: } w.close(); - _vm->_party._realPartyCount = _vm->_party._partyCount; - _vm->_party._mazeId = _vm->_party._priorMazeId; + _vm->_party->_realPartyCount = _vm->_party->_partyCount; + _vm->_party->_mazeId = _vm->_party->_priorMazeId; - _vm->_party.copyPartyToRoster(_vm->_roster); + _vm->_party->copyPartyToRoster(_vm->_roster); _vm->_saves->writeCharFile(); breakFlag = true; break; @@ -242,7 +242,7 @@ start: case Common::KEYCODE_d: break; case Common::KEYCODE_r: - if (_vm->_party._partyCount > 0) { + if (_vm->_party->_partyCount > 0) { // TODO } break; @@ -299,8 +299,8 @@ void Interface::loadCharIcons() { } void Interface::loadPartyIcons() { - for (int i = 0; i < _vm->_party._partyCount; ++i) - _partyFaces[i] = &_charFaces[_vm->_party._partyMembers[i]]; + for (int i = 0; i < _vm->_party->_partyCount; ++i) + _partyFaces[i] = &_charFaces[_vm->_party->_partyMembers[i]]; } void Interface::setupBackground() { @@ -315,19 +315,19 @@ void Interface::assembleBorder() { _globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8)); // Draw the animating bat character used to show when levitate is active - _borderSprites.draw(screen._windows[0], _vm->_party._levitateActive ? _batUIFrame + 16 : 16, + _borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16, Common::Point(0, 82)); _batUIFrame = (_batUIFrame + 1) % 12; // Draw UI element to indicate whether can spot hidden doors _borderSprites.draw(screen, - (_thinWall && _vm->_party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, + (_thinWall && _vm->_party->checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, Common::Point(194, 91)); _spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12; // Draw UI element to indicate whether can sense danger _borderSprites.draw(screen, - (_vm->_dangerSenseAllowed && _vm->_party.checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40, + (_vm->_dangerSenseAllowed && _vm->_party->checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40, Common::Point(107, 9)); _dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12; @@ -344,7 +344,7 @@ void Interface::assembleBorder() { else if (_vm->_face2State == 2) _face2UIFrame = 0; - if (!_vm->_party._clairvoyanceActive) { + if (!_vm->_party->_clairvoyanceActive) { _face1UIFrame = 0; _face2UIFrame = 8; } @@ -358,54 +358,54 @@ void Interface::assembleBorder() { // Draw resistence indicators if (!screen._windows[10]._enabled && !screen._windows[2]._enabled && screen._windows[38]._enabled) { - _fecpSprites.draw(screen, _vm->_party._fireResistence ? 1 : 0, + _fecpSprites.draw(screen, _vm->_party->_fireResistence ? 1 : 0, Common::Point(2, 2)); - _fecpSprites.draw(screen, _vm->_party._electricityResistence ? 3 : 2, + _fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 3 : 2, Common::Point(219, 2)); - _fecpSprites.draw(screen, _vm->_party._coldResistence ? 5 : 4, + _fecpSprites.draw(screen, _vm->_party->_coldResistence ? 5 : 4, Common::Point(2, 134)); - _fecpSprites.draw(screen, _vm->_party._poisonResistence ? 7 : 6, + _fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 7 : 6, Common::Point(219, 134)); } else { - _fecpSprites.draw(screen, _vm->_party._fireResistence ? 9 : 8, + _fecpSprites.draw(screen, _vm->_party->_fireResistence ? 9 : 8, Common::Point(8, 8)); - _fecpSprites.draw(screen, _vm->_party._electricityResistence ? 10 : 11, + _fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 10 : 11, Common::Point(219, 8)); - _fecpSprites.draw(screen, _vm->_party._coldResistence ? 12 : 13, + _fecpSprites.draw(screen, _vm->_party->_coldResistence ? 12 : 13, Common::Point(8, 134)); - _fecpSprites.draw(screen, _vm->_party._poisonResistence ? 14 : 15, + _fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 14 : 15, Common::Point(219, 134)); } // Draw UI element for blessed _blessSprites.draw(screen, 16, Common::Point(33, 137)); - if (_vm->_party._blessedActive) { + if (_vm->_party->_blessedActive) { _blessedUIFrame = (_blessedUIFrame + 1) % 4; _blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137)); } // Draw UI element for power shield - if (_vm->_party._powerShieldActive) { + if (_vm->_party->_powerShieldActive) { _powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4; _blessSprites.draw(screen, _powerShieldUIFrame + 4, Common::Point(55, 137)); } // Draw UI element for holy bonus - if (_vm->_party._holyBonusActive) { + if (_vm->_party->_holyBonusActive) { _holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4; _blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137)); } // Draw UI element for heroism - if (_vm->_party._heroismActive) { + if (_vm->_party->_heroismActive) { _heroismUIFrame = (_heroismUIFrame + 1) % 4; _blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137)); } // Draw direction character if direction sense is active - if (_vm->_party.checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) { - const char *dirText = DIRECTION_TEXT[_vm->_party._mazeDirection]; + if (_vm->_party->checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) { + const char *dirText = DIRECTION_TEXT[_vm->_party->_mazeDirection]; Common::String msg = Common::String::format( "\002""08\003""c\013""139\011""116%c\014""d\001", *dirText); screen._windows[0].writeString(msg); @@ -426,7 +426,7 @@ void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool for (posIndex = 0; posIndex < 4; ++posIndex) { charId = xeenSideChars[charIndex]; - bool isInParty = _vm->_party.isInParty(charId); + bool isInParty = _vm->_party->isInParty(charId); if (charId == 0xff) { while ((int)_buttons.size() > (7 + posIndex)) @@ -469,10 +469,10 @@ void Interface::charIconsPrint(bool updateFlag) { _restoreSprites.draw(screen, 0, Common::Point(8, 149)); // Handle drawing the party faces - for (int idx = 0; idx < (stateFlag ? _vm->_party._combatPartyCount : - _vm->_party._partyCount); ++idx) { + for (int idx = 0; idx < (stateFlag ? _vm->_party->_combatPartyCount : + _vm->_party->_partyCount); ++idx) { int charIndex = stateFlag ? _combatCharIds[idx] : idx; - PlayerStruct &ps = _vm->_party._activeParty[charIndex]; + PlayerStruct &ps = _vm->_party->_activeParty[charIndex]; Condition charCondition = ps.worstCondition(); int charFrame = FACE_CONDITION_FRAMES[charCondition]; @@ -485,10 +485,10 @@ void Interface::charIconsPrint(bool updateFlag) { } if (!_hpSprites.empty()) { - for (int idx = 0; idx < (stateFlag ? _vm->_party._combatPartyCount : - _vm->_party._partyCount); ++idx) { + for (int idx = 0; idx < (stateFlag ? _vm->_party->_combatPartyCount : + _vm->_party->_partyCount); ++idx) { int charIndex = stateFlag ? _combatCharIds[idx] : idx; - PlayerStruct &ps = _vm->_party._activeParty[charIndex]; + PlayerStruct &ps = _vm->_party->_activeParty[charIndex]; // Draw the Hp bar int maxHp = ps.getMaxHp(); @@ -555,7 +555,7 @@ void Interface::draw3d(bool updateFlag) { } MazeObject &objObject = map._mobData._objects[_objNumber]; - Direction partyDirection = _vm->_party._mazeDirection; + Direction partyDirection = _vm->_party->_mazeDirection; int objNum = _objNumber - 1; // Loop to update the frame numbers for each maze object, applying the animation frame @@ -2312,4 +2312,102 @@ void Interface::updateAutoMap() { // TODO } +/** + * Waits for a keypress or click, whilst still allowing the game scene to + * be animated. + */ +void Interface::wait() { + EventsManager &events = *_vm->_events; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Scripts &scripts = *_vm->_scripts; + const Common::Rect waitBounds(8, 8, 224, 140); + + while (!_vm->shouldQuit()) { + events.updateGameCounter(); + draw3d(true); + + // Wait for a frame + while (!_vm->shouldQuit()) { + events.pollEventsAndWait(); + checkEvents(_vm); + } while (!_buttonValue && events.timeElapsed() < 1 && !_vm->_party->_partyDead); + + if (!_buttonValue && !_vm->_party->_partyDead) + continue; + + if (_buttonValue == Common::KEYCODE_SPACE || + (events._leftButton && waitBounds.contains(events._mousePos))) { + int lookupId = map.mazeLookup(party._mazePosition, + WALL_NUMBERS[party._mazeDirection][2]); + + bool eventsFlag = true; + switch (lookupId) { + case 1: + if (!map._isOutdoors) { + scripts.openGrate(13, 1); + eventsFlag = _buttonValue != 0; + } + + case 6: + if (!map._isOutdoors) { + scripts.openGrate(9, 0); + eventsFlag = _buttonValue != 0; + } + break; + case 9: + if (!map._isOutdoors) { + scripts.openGrate(6, 0); + eventsFlag = _buttonValue != 0; + } + break; + case 13: + if (!map._isOutdoors) { + scripts.openGrate(1, 1); + eventsFlag = _buttonValue != 0; + } + break; + default: + break; + } + if (eventsFlag) { + scripts.checkEvents(); + if (_vm->shouldQuit()) + return; + } + } + + switch (_buttonValue) { + case Common::KEYCODE_TAB: + // Stop mosters doing any movement + _vm->_moveMonsters = false; + warning("TODO: showControlPanel"); + break; + + case Common::KEYCODE_SPACE: + case Common::KEYCODE_w: + // Wait one turn + chargeStep(); + moveMonsters(); + _upDoorText = false; + _flipDefaultGround = !_flipDefaultGround; + _flipGround = !_flipGround; + break; + default: + break; + } + } +} + +void Interface::chargeStep() { + if (_vm->_party->_partyDead) { + _vm->_party->changeTime(_vm->_map->_isOutdoors ? 10 : 1); + if (!_tillMove) { + moveMonsters(); + } + + _tillMove = 3; + } +} + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index df06f5d86b..c6fee9e0d4 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -63,7 +63,6 @@ private: int _holyBonusUIFrame; int _heroismUIFrame; int _flipUIFrame; - bool _newDay; bool _buttonsLoaded; Common::String _interfaceText; int _hiliteChar; @@ -74,6 +73,7 @@ private: byte _tillMove; bool _thinWall; int _overallFrame; + bool _upDoorText; void initDrawStructs(); @@ -85,8 +85,6 @@ private: void setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag); - void charIconsPrint(bool updateFlag); - void drawViewBackground(int bgType); void moveCharacterToRoster(); @@ -100,6 +98,8 @@ private: void setMazeBits(); void updateAutoMap(); + + void chargeStep(); public: Interface(XeenEngine *vm); @@ -116,6 +116,10 @@ public: void startup(); void mainIconsPrint(); + + void charIconsPrint(bool updateFlag); + + void wait(); }; } // End of namespace Xeen diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 93c3d9a679..1f927112b8 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -165,7 +165,7 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2 /*------------------------------------------------------------------------*/ IndoorDrawList::IndoorDrawList() : - _sky(_data[1]), _ground(_data[2]), _horizon(_data[28]), + _sky1(_data[0]), _sky2(_data[1]), _ground(_data[2]), _horizon(_data[28]), _swl_0F1R(_data[146]), _swl_0F1L(_data[144]), _swl_1F1R(_data[134]), _swl_1F1L(_data[133]), _swl_2F2R(_data[110]), _swl_2F1R(_data[109]), _swl_2F1L(_data[108]), _swl_2F2L(_data[107]), _swl_3F1R(_data[ 78]), @@ -378,8 +378,8 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) { void InterfaceMap::setIndoorsMonsters() { Combat &combat = *_vm->_combat; Map &map = *_vm->_map; - Common::Point mazePos = _vm->_party._mazePosition; - Direction dir = _vm->_party._mazeDirection; + Common::Point mazePos = _vm->_party->_mazePosition; + Direction dir = _vm->_party->_mazeDirection; const int INDOOR_MONSTERS_Y[4] = { 2, 34, 53, 59 }; combat.clear(); @@ -645,8 +645,8 @@ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster } void InterfaceMap::setIndoorsObjects() { - Common::Point mazePos = _vm->_party._mazePosition; - Direction dir = _vm->_party._mazeDirection; + Common::Point mazePos = _vm->_party->_mazePosition; + Direction dir = _vm->_party->_mazeDirection; Common::Point pt; _objNumber = 0; @@ -871,8 +871,8 @@ void InterfaceMap::setIndoorsObjects() { void InterfaceMap::setIndoorsWallPics() { Map &map = *_vm->_map; - const Common::Point &mazePos = _vm->_party._mazePosition; - Direction dir = _vm->_party._mazeDirection; + const Common::Point &mazePos = _vm->_party->_mazePosition; + Direction dir = _vm->_party->_mazeDirection; Common::fill(&_wp[0], &_wp[20], -1); @@ -1912,7 +1912,7 @@ void InterfaceMap::drawIndoors() { _indoorList._swl_0F1R._frame = 25; } - map.cellFlagLookup(_vm->_party._mazePosition); + map.cellFlagLookup(_vm->_party->_mazePosition); // WORKAROUND: Original did an array lookup on _skySprites. // Was this a feature for multiple skys that was abandoned? @@ -1922,19 +1922,19 @@ void InterfaceMap::drawIndoors() { if (_vm->_openDoor) { Common::Point pt( - _vm->_party._mazePosition.x + SCREEN_POSITIONING_X[ - _vm->_party._mazeDirection][_vm->_party._mazePosition.x], - _vm->_party._mazePosition.y + SCREEN_POSITIONING_Y[ - _vm->_party._mazeDirection][_vm->_party._mazePosition.y] + _vm->_party->_mazePosition.x + SCREEN_POSITIONING_X[ + _vm->_party->_mazeDirection][_vm->_party->_mazePosition.x], + _vm->_party->_mazePosition.y + SCREEN_POSITIONING_Y[ + _vm->_party->_mazeDirection][_vm->_party->_mazePosition.y] ); map.cellFlagLookup(pt); - _indoorList._sky._sprites = &map._skySprites; + _indoorList._sky2._sprites = &map._skySprites; } else { - _indoorList._sky._sprites = _indoorList[0]._sprites; + _indoorList._sky2._sprites = _indoorList[0]._sprites; } - _indoorList._sky._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0; + _indoorList._sky2._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0; _indoorList._ground._flags = _flipDefaultGround ? SPRFLAG_HORIZ_FLIPPED : 0; _indoorList._horizon._frame = 7; @@ -1943,7 +1943,7 @@ void InterfaceMap::drawIndoors() { // Check for any character shooting _isShooting = false; - for (int i = 0; i < _vm->_party._partyCount; ++i) { + for (int i = 0; i < _vm->_party->_partyCount; ++i) { if (_vm->_combat->_shooting[i]) _isShooting = true; } diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index fd807a03d2..be17ef0024 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -50,7 +50,7 @@ public: class IndoorDrawList { public: DrawStruct _data[170]; - DrawStruct &_sky; + DrawStruct &_sky1, &_sky2; DrawStruct &_ground; DrawStruct &_horizon; DrawStruct * const _groundTiles; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 99fe5ada0b..bef0511c81 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -887,7 +887,7 @@ void Map::load(int mapId) { } _stepped = true; - _vm->_party._mazeId = mapId; + _vm->_party->_mazeId = mapId; _vm->_events->clearEvents(); _sideObjects = 1; @@ -970,7 +970,7 @@ void Map::load(int mapId) { if (isDarkCc && mapId == 50) mazeDataP->setAllTilesStepped(); - if (!isDarkCc && _vm->_party._gameFlags[25] && + if (!isDarkCc && _vm->_party->_gameFlags[25] && (mapId == 42 || mapId == 43 || mapId == 4)) { mazeDataP->clearCellSurfaces(); } @@ -1004,14 +1004,14 @@ void Map::load(int mapId) { _headData.synchronize(headFile); headFile.close(); - if (!isDarkCc && _vm->_party._mazeId) + if (!isDarkCc && _vm->_party->_mazeId) _mobData._monsters.clear(); if (!isDarkCc && mapId == 15) { if ((_mobData._monsters[0]._position.x > 31 || _mobData._monsters[0]._position.y > 31) && (_mobData._monsters[1]._position.x > 31 || _mobData._monsters[1]._position.y > 31) && (_mobData._monsters[2]._position.x > 31 || _mobData._monsters[2]._position.y > 31)) { - _vm->_party._gameFlags[56] = true; + _vm->_party->_gameFlags[56] = true; } } } @@ -1029,7 +1029,7 @@ void Map::load(int mapId) { // TODO: Switch setting flags that don't seem to ever be used // Reload the monster data for the main maze that we're loading - mapId = _vm->_party._mazeId; + mapId = _vm->_party->_mazeId; Common::String filename = Common::String::format("maze%c%03d.mob", (mapId >= 100) ? 'x' : '0', mapId); File mobFile(filename, *_vm->_saves); @@ -1039,10 +1039,10 @@ void Map::load(int mapId) { // Load sprites for the objects for (uint i = 0; i < _mobData._objectSprites.size(); ++i) { - if (_vm->_party._cloudsEnd && _mobData._objectSprites[i]._spriteId == 85 && + if (_vm->_party->_cloudsEnd && _mobData._objectSprites[i]._spriteId == 85 && mapId == 27 && isDarkCc) { // TODO: Flags set that don't seem to be used - } else if (mapId == 12 && _vm->_party._gameFlags[43] && + } else if (mapId == 12 && _vm->_party->_gameFlags[43] && _mobData._objectSprites[i]._spriteId == 118 && !isDarkCc) { filename = "085.obj"; _mobData._objectSprites[0]._spriteId = 85; @@ -1081,7 +1081,6 @@ void Map::load(int mapId) { if (_isOutdoors) { warning("TODO"); // Sound loading - _skySprites.load(isDarkCc ? "night.sky" : "sky.sky"); _groundSprites.load("water.out"); _tileSprites.load("outdoor.til"); outdoorList._skySprite._sprites = &_skySprites; @@ -1102,7 +1101,6 @@ void Map::load(int mapId) { } else { warning("TODO"); // Sound loading - _skySprites.load(isDarkCc ? "night.sky" : "sky.sky"); _mazeSkySprites.load(Common::String::format("%s.sky", TERRAIN_TYPES[_mazeData[0]._wallKind])); _groundSprites.load(Common::String::format("%s.gnd", @@ -1193,18 +1191,20 @@ void Map::load(int mapId) { indoorList._horizon._sprites = nullptr; } } + + loadSky(); } -int Map::mazeLookup(const Common::Point &pt, int directionLayerIndex) { +int Map::mazeLookup(const Common::Point &pt, int layerShift) { Common::Point pos = pt; - int mapId = _vm->_party._mazeId; + int mapId = _vm->_party->_mazeId; if (pt.x < -16 || pt.y < -16 || pt.x >= 32 || pt.y >= 32) error("Invalid coordinate"); // Find the correct maze data out of the set to use _mazeDataIndex = 0; - while (_mazeData[_mazeDataIndex]._mazeId != _vm->_party._mazeId) + while (_mazeData[_mazeDataIndex]._mazeId != _vm->_party->_mazeId) ++_mazeDataIndex; // Handle map changing to the north or south as necessary @@ -1259,7 +1259,7 @@ int Map::mazeLookup(const Common::Point &pt, int directionLayerIndex) { _currentSteppedOn = _mazeData[_mazeDataIndex]._steppedOnTiles[pos.y][pos.x]; } - return (_mazeData[_mazeDataIndex]._wallData[pos.y][pos.x]._data >> (directionLayerIndex * 4)) & 0xF; + return (_mazeData[_mazeDataIndex]._wallData[pos.y][pos.x]._data >> layerShift) & 0xF; } else { _currentSteppedOn = _isOutdoors; @@ -1312,7 +1312,7 @@ void Map::saveMaze() { void Map::cellFlagLookup(const Common::Point &pt) { Common::Point pos = pt; - int mapId = _vm->_party._mazeId; + int mapId = _vm->_party->_mazeId; _mazeDataIndex = 0; while (_mazeData[_mazeDataIndex]._mazeId != mapId) ++_mazeDataIndex; @@ -1364,11 +1364,11 @@ void Map::setCellSurfaceFlags(const Common::Point &pt, int bits) { int Map::getCell(int idx) { - int mapId = _vm->_party._mazeId; - Direction dir = _vm->_party._mazeDirection; + int mapId = _vm->_party->_mazeId; + Direction dir = _vm->_party->_mazeDirection; Common::Point pt( - _vm->_party._mazePosition.x + SCREEN_POSITIONING_X[_vm->_party._mazeDirection][idx], - _vm->_party._mazePosition.y + SCREEN_POSITIONING_Y[_vm->_party._mazeDirection][idx] + _vm->_party->_mazePosition.x + SCREEN_POSITIONING_X[_vm->_party->_mazeDirection][idx], + _vm->_party->_mazePosition.y + SCREEN_POSITIONING_Y[_vm->_party->_mazeDirection][idx] ); if (pt.x > 31 || pt.y > 31) { @@ -1484,10 +1484,19 @@ int Map::getCell(int idx) { _currentSurfaceId = _mazeData[_mazeDataIndex]._cells[pt.y][pt.x]._surfaceId; _currentWall = wallLayers; - return (_currentWall._data >> (WALL_NUMBERS[dir][idx * 2] * 4)) & 0xF; + return (_currentWall._data >> WALL_NUMBERS[dir][idx]) & 0xF; } return _currentWall._data; } +void Map::loadSky() { + Party &party = *_vm->_party; + + party._isNight = party._minutes < (5 * 60) || party._minutes >= (21 * 60); + _skySprites.load(((party._mazeId >= 89 && party._mazeId <= 112) || + party._mazeId == 128 || party._mazeId == 129) || !party._isNight + ? "sky.sky" : "night.sky"); +} + } // End of namespace Xeen diff --git a/engines/xeen/map.h b/engines/xeen/map.h index c97de72a23..ae8ad28efd 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -392,7 +392,7 @@ public: void load(int mapId); - int mazeLookup(const Common::Point &pt, int directionLayerIndex); + int mazeLookup(const Common::Point &pt, int layerShift); void cellFlagLookup(const Common::Point &pt); @@ -404,6 +404,7 @@ public: MazeData mazeData() { return _mazeData[0]; } + void loadSky(); }; } // End of namespace Xeen diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index ad6d2145de..6d5cc22ffa 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -23,9 +23,11 @@ #include "common/scummsys.h" #include "common/algorithm.h" #include "xeen/party.h" +#include "xeen/dialogs_error.h" #include "xeen/files.h" -#include "xeen/xeen.h" +#include "xeen/resources.h" #include "xeen/saves.h" +#include "xeen/xeen.h" namespace Xeen { @@ -155,6 +157,16 @@ int PlayerStruct::getMaxHp() { return 20; } +int PlayerStruct::getStat(int statNum, int v2) { + // TODO + return 10; +} + +bool PlayerStruct::charSavingThrow() { + // TODO + return false; +} + /*------------------------------------------------------------------------*/ void Roster::synchronize(Common::Serializer &s) { @@ -167,7 +179,7 @@ void Roster::synchronize(Common::Serializer &s) { /*------------------------------------------------------------------------*/ -Party::Party() { +Party::Party(XeenEngine *vm): _vm(vm) { _partyCount = 0; _realPartyCount = 0; Common::fill(&_partyMembers[0], &_partyMembers[8], 0); @@ -216,6 +228,9 @@ Party::Party() { Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false); _combatPartyCount = 0; + _partyDead = false; + _newDay = false; + _isNight = false; } void Party::synchronize(Common::Serializer &s) { @@ -343,4 +358,190 @@ void Party::copyPartyToRoster(Roster &r) { } } +/** + * Adds time to the party's playtime, taking into account the effect of any + * stat modifier changes + */ +void Party::changeTime(int numMinutes) { + bool killed = false; + + if (((_minutes + numMinutes) / 480) != (_minutes / 480)) { + for (int idx = 0; idx < _partyCount; ++idx) { + PlayerStruct &player = _activeParty[idx]; + + if (!player._conditions[DEAD] && !player._conditions[STONED] && + !player._conditions[ERADICATED]) { + for (int statNum = 0; statNum < TOTAL_STATS; ++statNum) { + int statVal = player.getStat(statNum, 0); + if (statVal < 1) + player._conditions[DEAD] = 1; + } + } + + // Handle heart broken condition becoming depression + if (player._conditions[HEART_BROKEN]) { + if (++player._conditions[HEART_BROKEN] > 10) { + player._conditions[HEART_BROKEN] = 0; + player._conditions[DEPRESSED] = 1; + } + } + + // Handle poisoning + if (!player._conditions[POISONED]) { + if (_vm->getRandomNumber(9) != 1 || !player.charSavingThrow()) + player._conditions[POISONED] *= 2; + else + // Poison wears off + player._conditions[POISONED] = 0; + } + + // Handle poisoning + if (!player._conditions[DISEASED]) { + if (_vm->getRandomNumber(9) != 1 || !player.charSavingThrow()) + player._conditions[DISEASED] *= 2; + else + // Disease wears off + player._conditions[DISEASED] = 0; + } + + // Handle insane status + if (player._conditions[INSANE]) + player._conditions[INSANE]++; + + if (player._conditions[DEAD]) { + if (++player._conditions[DEAD] == 0) + player._conditions[DEAD] = -1; + } + + if (player._conditions[STONED]) { + if (++player._conditions[STONED] == 0) + player._conditions[STONED] = -1; + } + + if (player._conditions[ERADICATED]) { + if (++player._conditions[ERADICATED] == 0) + player._conditions[ERADICATED] = -1; + } + + if (player._conditions[IN_LOVE]) { + if (++player._conditions[IN_LOVE] > 10) { + player._conditions[IN_LOVE] = 0; + player._conditions[HEART_BROKEN] = 1; + } + } + + player._conditions[WEAK] = player._conditions[DRUNK]; + player._conditions[DRUNK] = 0; + + if (player._conditions[DEPRESSED]) { + player._conditions[DEPRESSED] = (player._conditions[DEPRESSED] + 1) % 4; + } + } + } + + // Increment the time + addTime(numMinutes); + + for (int idx = 0; idx < _partyCount; ++idx) { + PlayerStruct &player = _activeParty[idx]; + + if (player._conditions[CONFUSED] && _vm->getRandomNumber(2) == 1) { + if (player.charSavingThrow()) { + player._conditions[CONFUSED] = 0; + } else { + player._conditions[CONFUSED]--; + } + } + + if (player._conditions[PARALYZED] && _vm->getRandomNumber(4) == 1) + player._conditions[PARALYZED]--; + } + + if (killed) + _vm->_interface->charIconsPrint(true); + + if (_isNight != (_minutes < (5 * 60) || _minutes >= (21 * 60))) + _vm->_map->loadSky(); +} + +void Party::addTime(int numMinutes) { + int day = _day; + _minutes += numMinutes; + + // If the total minutes has exceeded a day, move to next one + while (_minutes >= (24 * 60)) { + _minutes -= 24 * 60; + if (++_day >= 100) { + _day -= 100; + ++_year; + } + } + + if ((_day % 10) == 1 || numMinutes > (24 * 60)) { + if (_day != day) { + warning("TODO: resetBlacksmith? and giveInterest?"); + } + } + + if (_day != day) + _newDay = true; + + if (_newDay && _minutes >= 300) { + if (_vm->_mode != MODE_9 && _vm->_mode != MODE_17) { + resetTemps(); + if (_rested || _vm->_mode == MODE_5) { + _rested = false; + } else { + for (int idx = 0; idx < _partyCount; ++idx) { + if (_activeParty[idx]._conditions[WEAK] >= 0) + _activeParty[idx]._conditions[WEAK]++; + } + + ErrorScroll::show(_vm, THE_PARTY_NEEDS_REST, WT_NONFREEZED_WAIT); + } + + _vm->_interface->charIconsPrint(true); + } + + _newDay = false; + } +} + +void Party::resetTemps() { + for (int idx = 0; idx < _partyCount; ++idx) { + PlayerStruct &player = _activeParty[idx]; + + player._magicResistence._temporary = 0; + player._energyResistence._temporary = 0; + player._poisonResistence._temporary = 0; + player._electricityResistence._temporary = 0; + player._coldResistence._temporary = 0; + player._fireResistence._temporary = 0; + player._ACTemp = 0; + player._level._temporary = 0; + player._luck._temporary = 0; + player._accuracy._temporary = 0; + player._speed._temporary = 0; + player._endurance._temporary = 0; + player._personality._temporary = 0; + player._intellect._temporary = 0; + player._might._temporary = 0; + } + + _poisonResistence = 0; + _coldResistence = 0; + _electricityResistence = 0; + _fireResistence = 0; + _lightCount = 0; + _levitateActive = false; + _walkOnWaterActive = false; + _wizardEyeActive = false; + _clairvoyanceActive = false; + _heroismActive = false; + _holyBonusActive = false; + _powerShieldActive = false; + _blessedActive = false; +} + + } // End of namespace Xeen diff --git a/engines/xeen/party.h b/engines/xeen/party.h index d8fe2ab79d..75a6c2b07b 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -66,6 +66,7 @@ enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, #define TOTAL_CHARACTERS 30 #define XEEN_TOTAL_CHARACTERS 24 #define MAX_ACTIVE_PARTY 6 +#define TOTAL_STATS 7 class XeenEngine; @@ -133,6 +134,10 @@ public: int getAge(int partyYear, bool ignoreTemp); int getMaxHp(); + + int getStat(int statNum, int v2); + + bool charSavingThrow(); }; class Roster: public Common::Array<PlayerStruct> { @@ -143,6 +148,8 @@ public: }; class Party { +private: + XeenEngine *_vm; public: // Dynamic data that's saved int _partyCount; @@ -202,8 +209,11 @@ public: // Other party related runtime data Common::Array<PlayerStruct> _activeParty; int _combatPartyCount; + bool _partyDead; + bool _newDay; + bool _isNight; public: - Party(); + Party(XeenEngine *vm); void synchronize(Common::Serializer &s); @@ -212,6 +222,12 @@ public: bool isInParty(int charId); void copyPartyToRoster(Roster &r); + + void changeTime(int numMinutes); + + void addTime(int numMinutes); + + void resetTemps(); }; } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 51f26fe668..085f84aa73 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -66,6 +66,8 @@ const char *const OPTIONS_TITLE = "\v117Copyright (c) 1993 NWC, Inc.\n" "All Rights Reserved\x01"; +const char *const THE_PARTY_NEEDS_REST = "\x0B""012The Party needs rest!"; + const char *const TERRAIN_TYPES[6] = { "town", "cave", "towr", "cstl", "dung", "scfi" }; @@ -392,43 +394,27 @@ const int DIRECTION_ANIM_POSITIONS[4][4] = { { 0, 1, 2, 3 }, { 3, 0, 1, 2 }, { 2, 3, 0, 1 }, { 1, 2, 3, 0 } }; -const byte WALL_NUMBERS[4][96] = { +const byte WALL_NUMBERS[4][48] = { { - 3, 0, 0, 0, 3, 0, 2, 0, 3, 0, 3, 0, - 0, 0, 3, 0, 2, 0, 3, 0, 3, 0, 0, 0, - 3, 0, 0, 0, 3, 0, 2, 0, 3, 0, 2, 0, - 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, - 0, 0, 3, 0, 0, 0, 3, 0, 2, 0, 3, 0, - 2, 0, 3, 0, 2, 0, 3, 0, 2, 0, 3, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, - 2, 0, 2, 0, 0, 0, 0, 0, 1, 0, 1, 0 + 12, 0, 12, 8, 12, 12, 0, 12, 8, 12, 12, 0, + 12, 0, 12, 8, 12, 8, 12, 12, 0, 12, 0, 12, + 0, 12, 0, 12, 8, 12, 8, 12, 8, 12, 8, 12, + 0, 0, 0, 0, 8, 8, 8, 8, 0, 0, 4, 4 }, { - 2, 0, 3, 0, 2, 0, 1, 0, 2, 0, 2, 0, - 3, 0, 2, 0, 1, 0, 2, 0, 2, 0, 3, 0, - 2, 0, 3, 0, 2, 0, 1, 0, 2, 0, 1, 0, - 2, 0, 2, 0, 3, 0, 2, 0, 3, 0, 2, 0, - 3, 0, 2, 0, 3, 0, 2, 0, 1, 0, 2, 0, - 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, - 3, 0, 3, 0, 3, 0, 3, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 8, 12, 8, 4, 8, 8, 12, 8, 4, 8, 8, 12, + 8, 12, 8, 4, 8, 4, 8, 8, 12, 8, 12, 8, + 12, 8, 12, 8, 4, 8, 4, 8, 4, 8, 4, 8, + 12, 12, 12, 12, 4, 4, 4, 4, 0, 0, 0, 0 }, { - 1, 0, 2, 0, 1, 0, 0, 0, 1, 0, 1, 0, - 2, 0, 1, 0, 0, 0, 1, 0, 1, 0, 2, 0, - 1, 0, 2, 0, 1, 0, 0, 0, 1, 0, 0, 0, - 1, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, - 2, 0, 1, 0, 2, 0, 1, 0, 0, 0, 1, 0, - 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, - 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0 + 4, 8, 4, 0, 4, 4, 8, 4, 0, 4, 4, 8, + 4, 8, 4, 0, 4, 0, 4, 4, 8, 4, 8, 4, + 8, 4, 8, 4, 0, 4, 0, 4, 0, 4, 0, 4, + 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 12, 12 }, { - 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, - 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 3, 0, - 3, 0, 3, 0, 0, 0, 0, 0, 2, 0, 2, 0 + 0, 4, 0, 12, 0, 0, 4, 0, 12, 0, 0, 4, + 0, 4, 0, 12, 0, 12, 0, 0, 4, 0, 4, 0, + 4, 0, 4, 0, 12, 0, 12, 0, 12, 0, 12, 0, + 4, 4, 4, 4, 12, 12, 12, 12, 0, 0, 8, 8 } }; diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 0ef9211288..f6bcffaf4e 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -32,6 +32,8 @@ extern const char *const CREDITS; extern const char *const OPTIONS_TITLE; +extern const char *const THE_PARTY_NEEDS_REST; + extern const char *const TERRAIN_TYPES[6]; extern const char *const SURFACE_TYPE_NAMES[15]; @@ -88,7 +90,7 @@ extern const int OUTDOOR_OBJECT_Y[2][12]; extern const int DIRECTION_ANIM_POSITIONS[4][4]; -extern const byte WALL_NUMBERS[4][96]; +extern const byte WALL_NUMBERS[4][48]; extern const int DRAW_NUMBERS[25]; diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 0a864aa2cb..5a36a32a7e 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -61,4 +61,21 @@ void MazeEvents::synchronize(XeenSerializer &s) { } } +/*------------------------------------------------------------------------*/ + +Scripts::Scripts(XeenEngine *vm) : _vm(vm) { +} + +void Scripts::checkEvents() { + // TODO +} + +void Scripts::giveTreasure() { + // TODO +} + +void Scripts::openGrate(int v1, int v2) { + // TODO +} + } // End of namespace Xeen diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 727d37f681..4f49018e2b 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -95,6 +95,8 @@ enum Opcode { OP_PlayCD = 0x3C }; +class XeenEngine; + class MazeEvent { public: Common::Point _position; @@ -115,6 +117,19 @@ public: void synchronize(XeenSerializer &s); }; +class Scripts { +private: + XeenEngine *_vm; +public: + Scripts(XeenEngine *vm); + + void checkEvents(); + + void giveTreasure(); + + void openGrate(int v1, int v2); +}; + } // End of namespace Xeen #endif /* XEEN_SCRIPTS_H */ diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 448ec0ec57..1d9a5c8abf 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -230,6 +230,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, int flags, int scale) const { + scale = 0; // ***DEBUG*** if (scale == 0) { drawOffset(dest, _index[frame]._offset1, destPos, flags); if (_index[frame]._offset2) diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 6b73de6939..b8f9030c85 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -42,8 +42,10 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _files = nullptr; _interface = nullptr; _map = nullptr; + _party = nullptr; _saves = nullptr; _screen = nullptr; + _scripts = nullptr; _sound = nullptr; _eventData = nullptr; _loadDarkSide = 1; @@ -63,8 +65,10 @@ XeenEngine::~XeenEngine() { delete _events; delete _interface; delete _map; + delete _party; delete _saves; delete _screen; + delete _scripts; delete _sound; delete _eventData; delete _files; @@ -84,8 +88,10 @@ void XeenEngine::initialize() { _events = new EventsManager(this); _interface = new Interface(this); _map = new Map(this); - _saves = new SavesManager(this, _party, _roster); + _party = new Party(this); + _saves = new SavesManager(this, *_party, _roster); _screen = new Screen(this); + _scripts = new Scripts(this); _screen->setupWindows(); _sound = new SoundManager(this); @@ -281,13 +287,13 @@ void XeenEngine::play() { if (getGameID() != GType_WorldOfXeen && !_loadDarkSide) { _loadDarkSide = true; - _party._mazeId = 29; - _party._mazeDirection = DIR_NORTH; - _party._mazePosition.x = 25; - _party._mazePosition.y = 21; + _party->_mazeId = 29; + _party->_mazeDirection = DIR_NORTH; + _party->_mazePosition.x = 25; + _party->_mazePosition.y = 21; } - _map->load(_party._mazeId); + _map->load(_party->_mazeId); _interface->startup(); if (_mode == MODE_0) { @@ -307,9 +313,22 @@ void XeenEngine::play() { _moveMonsters = true; + gameLoop(); +} + +void XeenEngine::gameLoop() { // Main game loop while (!shouldQuit()) { - _events->pollEventsAndWait(); + _map->cellFlagLookup(_party->_mazePosition); + if (_map->_currentIsEvent) { + _scripts->checkEvents(); + if (shouldQuit()) + return; + } + _scripts->giveTreasure(); + + // Wait loop + _interface->wait(); } } diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index e6bcd8c0b7..59816b0d91 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -41,6 +41,7 @@ #include "xeen/party.h" #include "xeen/saves.h" #include "xeen/screen.h" +#include "xeen/scripts.h" #include "xeen/sound.h" /** @@ -102,6 +103,8 @@ private: void play(); void pleaseWait(); + + void gameLoop(); protected: /** * Play the game @@ -131,14 +134,15 @@ public: FileManager *_files; Interface *_interface; Map *_map; + Party *_party; SavesManager *_saves; Screen *_screen; + Scripts *_scripts; SoundManager *_sound; Mode _mode; GameEvent _gameEvent; Common::SeekableReadStream *_eventData; Roster _roster; - Party _party; int _loadDarkSide; bool _dangerSenseAllowed; int _face1State; -- cgit v1.2.3 From ec294d662e7d54a9927c2b85ec430e1519be5de7 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 19 Jan 2015 12:13:03 -0500 Subject: XEEN: Add extra ending code for pausing turns --- engines/xeen/dialogs.cpp | 1 + engines/xeen/interface.cpp | 32 ++++++++++++++++++++++++++++++-- engines/xeen/interface.h | 7 ++++++- engines/xeen/party.cpp | 4 ++-- engines/xeen/party.h | 2 +- engines/xeen/sound.h | 2 ++ engines/xeen/xeen.cpp | 4 ++-- 7 files changed, 44 insertions(+), 8 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index 824e8249ce..d1662aeb68 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -52,6 +52,7 @@ void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResou bool ButtonContainer::checkEvents(XeenEngine *vm) { EventsManager &events = *vm->_events; + _buttonValue = 0; if (events._leftButton) { // Check whether any button is selected diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index e15c0574aa..8ff0b92d13 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -49,6 +49,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm( _thinWall = false; _overallFrame = 0; _upDoorText = false; + _steppingFX = 0; Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); initDrawStructs(); @@ -2316,7 +2317,7 @@ void Interface::updateAutoMap() { * Waits for a keypress or click, whilst still allowing the game scene to * be animated. */ -void Interface::wait() { +void Interface::perform() { EventsManager &events = *_vm->_events; Map &map = *_vm->_map; Party &party = *_vm->_party; @@ -2328,7 +2329,7 @@ void Interface::wait() { draw3d(true); // Wait for a frame - while (!_vm->shouldQuit()) { + do { events.pollEventsAndWait(); checkEvents(_vm); } while (!_buttonValue && events.timeElapsed() < 1 && !_vm->_party->_partyDead); @@ -2392,6 +2393,8 @@ void Interface::wait() { _upDoorText = false; _flipDefaultGround = !_flipDefaultGround; _flipGround = !_flipGround; + + stepTime(); break; default: break; @@ -2410,4 +2413,29 @@ void Interface::chargeStep() { } } +/** + * Handles incrementing game time + */ +void Interface::stepTime() { + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + doStepCode(); + + if (++party._ctr24 == 24) + party._ctr24 = 0; + + if (_buttonValue != Common::KEYCODE_SPACE && _buttonValue != Common::KEYCODE_w) { + _steppingFX ^= 1; + sound.playFX(_steppingFX + 7); + } + + _upDoorText = false; + _flipDefaultGround = !_flipDefaultGround; + _flipGround = !_flipGround; +} + +void Interface::doStepCode() { + // TODO +} + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index c6fee9e0d4..af26611e6d 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -74,6 +74,7 @@ private: bool _thinWall; int _overallFrame; bool _upDoorText; + int _steppingFX; void initDrawStructs(); @@ -100,6 +101,10 @@ private: void updateAutoMap(); void chargeStep(); + + void stepTime(); + + void doStepCode(); public: Interface(XeenEngine *vm); @@ -119,7 +124,7 @@ public: void charIconsPrint(bool updateFlag); - void wait(); + void perform(); }; } // End of namespace Xeen diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 6d5cc22ffa..4571bbe518 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -198,7 +198,7 @@ Party::Party(XeenEngine *vm): _vm(vm) { _cloudsEnd = false; _darkSideEnd = false; _worldEnd = false; - hour_maybe = 0; + _ctr24 = 0; _day = 0; _year = 0; _minutes = 0; @@ -273,7 +273,7 @@ void Party::synchronize(Common::Serializer &s) { s.syncAsUint16LE(_cloudsEnd); s.syncAsUint16LE(_darkSideEnd); s.syncAsUint16LE(_worldEnd); - s.syncAsUint16LE(hour_maybe); + s.syncAsUint16LE(_ctr24); s.syncAsUint16LE(_day); s.syncAsUint16LE(_year); s.syncAsUint16LE(_minutes); diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 75a6c2b07b..8db52df1a6 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -176,7 +176,7 @@ public: bool _cloudsEnd; bool _darkSideEnd; bool _worldEnd; - int hour_maybe; + int _ctr24; // TODO: Figure out proper name int _day; int _year; int _minutes; diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index 553b1c6f44..c1215249a9 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -42,6 +42,8 @@ public: void playSong(Common::SeekableReadStream &f) {} void playSample(const Common::SeekableReadStream *stream, int v2) {} + + void playFX(int id) {} }; } // End of namespace Xeen diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index b8f9030c85..e9b4d93de8 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -327,8 +327,8 @@ void XeenEngine::gameLoop() { } _scripts->giveTreasure(); - // Wait loop - _interface->wait(); + // Main user interface handler for waiting for and processing user input + _interface->perform(); } } -- cgit v1.2.3 From e559a99c2794c727d04adf4602f0aac1112af765 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 19 Jan 2015 15:29:57 -0500 Subject: XEEN: Initial implementation of drawMiniMap --- engines/xeen/interface.cpp | 502 +++++++++++++++++++++++++++++++++++++++------ engines/xeen/interface.h | 4 +- engines/xeen/map.cpp | 4 +- engines/xeen/map.h | 6 +- 4 files changed, 446 insertions(+), 70 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 8ff0b92d13..bcb406dcbe 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -722,7 +722,7 @@ void Interface::draw3d(bool updateFlag) { } animate3d(); - updateAutoMap(); + drawMiniMap(); if (_vm->_falling == 1) { error("TODO: Indoor falling"); @@ -808,7 +808,7 @@ void Interface::setMainButtons() { addButton(Common::Rect(235, 169, 259, 189), 176, &_iconSprites); addButton(Common::Rect(260, 169, 284, 189), 243, &_iconSprites); addButton(Common::Rect(286, 169, 310, 189), 177, &_iconSprites); - addButton(Common::Rect(236, 11, 308, 69), 61, &_iconSprites, false); + addButton(Common::Rect(236, 11, 308, 69), Common::KEYCODE_EQUALS, &_iconSprites, false); addButton(Common::Rect(239, 27, 312, 37), 49, &_iconSprites, false); addButton(Common::Rect(239, 37, 312, 47), 50, &_iconSprites, false); addButton(Common::Rect(239, 47, 312, 57), 51, &_iconSprites, false); @@ -2309,96 +2309,468 @@ void Interface::setMazeBits() { } } -void Interface::updateAutoMap() { - // TODO -} - -/** - * Waits for a keypress or click, whilst still allowing the game scene to - * be animated. - */ -void Interface::perform() { - EventsManager &events = *_vm->_events; +void Interface::drawMiniMap() { Map &map = *_vm->_map; Party &party = *_vm->_party; - Scripts &scripts = *_vm->_scripts; - const Common::Rect waitBounds(8, 8, 224, 140); + Screen &screen = *_vm->_screen; + Window &window1 = screen._windows[1]; - while (!_vm->shouldQuit()) { - events.updateGameCounter(); - draw3d(true); + if (screen._windows[2]._enabled || screen._windows[10]._enabled || + (!party._automapOn && !party._wizardEyeActive)) + return; - // Wait for a frame - do { - events.pollEventsAndWait(); - checkEvents(_vm); - } while (!_buttonValue && events.timeElapsed() < 1 && !_vm->_party->_partyDead); + int v, frame; + int frame2 = _overallFrame * 2; + bool eyeActive = party._wizardEyeActive; + if (party._automapOn) + party._wizardEyeActive = false; - if (!_buttonValue && !_vm->_party->_partyDead) - continue; + if (map._isOutdoors) { + _globalSprites.draw(window1, 15, Common::Point(237, 12)); - if (_buttonValue == Common::KEYCODE_SPACE || - (events._leftButton && waitBounds.contains(events._mousePos))) { - int lookupId = map.mazeLookup(party._mazePosition, - WALL_NUMBERS[party._mazeDirection][2]); + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 4); + frame = map.mazeDataCurrent()._surfaceTypes[v]; - bool eventsFlag = true; - switch (lookupId) { - case 1: - if (!map._isOutdoors) { - scripts.openGrate(13, 1); - eventsFlag = _buttonValue != 0; + if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, frame, Common::Point(xp, yp)); } + } + } - case 6: - if (!map._isOutdoors) { - scripts.openGrate(9, 0); - eventsFlag = _buttonValue != 0; + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 4); + frame = map.mazeData()._wallTypes[v]; + + if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, frame + 16, Common::Point(xp, yp)); } + } + } + + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 4); + + if (v != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, v + 32, Common::Point(xp, yp)); + } + } + } + } else { + frame2 = (frame2 + 2) % 8; + + // First draw cell back for positions in the map that have been revealed + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 0, 0xffff); + + if (v != 0xffff && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, 0, Common::Point(xp, yp)); + } + } + } + + // Draw tiles based on the surface for each revelaed tile + for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 0, 0xffff); + + if (v != 0xffff && !map._currentSurfaceId && + (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, + map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, + Common::Point(xp, yp)); + } + } + } + + v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0); + if (v != 0xffff && !map._currentSurfaceId && + (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, + map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, + Common::Point(232, 9)); + } + + // Right edge + for (int rowNum = 0, yp = 242, yDiff = -3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x - 4, party._mazePosition.y + yDiff), + 0, 0xffff); + + if (v != 0xffff && !map._currentSurfaceId && + (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, + map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, + Common::Point(232, yp)); + } + } + + // Top edge + for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, --xDiff, xp += 8) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + 4), + 0, 0xffff); + + if (v != 0xffff && !map._currentSurfaceId && + (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, + map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, + Common::Point(xp, 9)); + } + } + + // + for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE; + ++idx, --xDiff, xp += 10, yp -= 8) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x - 4, party._mazePosition.y - 3 + idx), + 12, 0xffff); + + switch (v) { + case 1: + frame = 18; + break; + case 3: + frame = 22; + break; + case 4: + case 13: + frame = 16; + break; + case 5: + case 8: + frame = 2; + break; + case 6: + frame = 30; + break; + case 7: + frame = 32; break; case 9: - if (!map._isOutdoors) { - scripts.openGrate(6, 0); - eventsFlag = _buttonValue != 0; - } + frame = 24; + break; + case 10: + frame = 28; + break; + case 11: + frame = 14; + break; + case 12: + frame = frame2 + 4; + break; + case 14: + frame = 24; + break; + case 15: + frame = 26; + break; + default: + frame = -1; break; + } + + if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) + map._tileSprites.draw(window1, frame, Common::Point(222, yp)); + + v = map.mazeLookup( + Common::Point(party._mazePosition.x - 3 + idx, party._mazePosition.y + 4), + 0); + + switch (v) { + case 1: + frame = 19; + break; + case 2: + frame = 35; + break; + case 3: + frame = 23; + break; + case 4: case 13: - if (!map._isOutdoors) { - scripts.openGrate(1, 1); - eventsFlag = _buttonValue != 0; - } + frame = 17; + break; + case 5: + case 8: + frame = 3; + break; + case 6: + frame = 31; + break; + case 7: + frame = 33; + break; + case 9: + frame = 21; + break; + case 10: + frame = 29; + break; + case 11: + frame = 15; + break; + case 12: + frame = frame2 + 5; + break; + case 14: + frame = 25; + break; + case 15: + frame = 27; break; default: + frame = -1; break; } - if (eventsFlag) { - scripts.checkEvents(); - if (_vm->shouldQuit()) - return; + + if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) + map._tileSprites.draw(window1, frame, Common::Point(xp, 4)); + } + + // + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; + ++rowNum, --yDiff, yp -= 8) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; + ++colNum, ++xDiff, xp += 10) { + if (colNum == 4 && rowNum == 4) { + // Center of the minimap + _globalSprites.draw(window1, party._mazeDirection + 1, + Common::Point(272, 40)); + } + + v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff, + party._mazePosition.y + yDiff), 12, 0xffff); + switch (v) { + case 1: + frame = 18; + break; + case 3: + frame = 22; + break; + case 4: + case 13: + frame = 16; + break; + case 5: + case 8: + frame = 2; + break; + case 6: + frame = 30; + break; + case 7: + frame = 32; + break; + case 9: + frame = 20; + break; + case 10: + frame = 28; + break; + case 11: + frame = 14; + break; + case 12: + frame = frame2 + 4; + break; + case 14: + frame = 24; + break; + case 15: + frame = 26; + break; + default: + frame = -1; + break; + } + + if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, frame, Common::Point(xp, yp)); + } + + v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff, + party._mazePosition.y + yDiff), 12, 0xffff); + switch (v) { + case 1: + frame = 19; + break; + case 2: + frame = 35; + break; + case 3: + frame = 23; + break; + case 4: + case 13: + frame = 17; + break; + case 5: + case 8: + frame = 3; + break; + case 6: + frame = 31; + break; + case 7: + frame = 33; + break; + case 9: + frame = 21; + break; + case 10: + frame = 29; + break; + case 11: + frame = 15; + break; + case 12: + frame = frame2 + 5; + break; + case 14: + frame = 25; + break; + case 15: + frame = 27; + break; + default: + frame = -1; + break; + } + + if (v == -1 && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, frame, Common::Point(xp, yp)); + } } } - switch (_buttonValue) { - case Common::KEYCODE_TAB: - // Stop mosters doing any movement - _vm->_moveMonsters = false; - warning("TODO: showControlPanel"); - break; + // Final loop + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 0, 0xffff); - case Common::KEYCODE_SPACE: - case Common::KEYCODE_w: - // Wait one turn - chargeStep(); - moveMonsters(); - _upDoorText = false; - _flipDefaultGround = !_flipDefaultGround; - _flipGround = !_flipGround; + if (v != 0xffff && !map._currentSurfaceId && + (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, 1, Common::Point(xp, yp)); + } + } + } + } + + if (map._isOutdoors) { + _globalSprites.draw(window1, party._mazeDirection + 1, + Common::Point(267, 36)); + } + + _globalSprites.draw(window1, 6, Common::Point(223, 3)); + party._wizardEyeActive = eyeActive; +} + +/** + * Waits for a keypress or click, whilst still allowing the game scene to + * be animated. + */ +void Interface::perform() { + EventsManager &events = *_vm->_events; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Scripts &scripts = *_vm->_scripts; + const Common::Rect waitBounds(8, 8, 224, 140); + + events.updateGameCounter(); + draw3d(true); + + // Wait for a frame + do { + events.pollEventsAndWait(); + checkEvents(_vm); + } while (!_buttonValue && events.timeElapsed() < 1 && !_vm->_party->_partyDead); - stepTime(); + if (!_buttonValue && !_vm->_party->_partyDead) + return; + + if (_buttonValue == Common::KEYCODE_SPACE || + (events._leftButton && waitBounds.contains(events._mousePos))) { + int lookupId = map.mazeLookup(party._mazePosition, + WALL_NUMBERS[party._mazeDirection][2]); + + bool eventsFlag = true; + switch (lookupId) { + case 1: + if (!map._isOutdoors) { + scripts.openGrate(13, 1); + eventsFlag = _buttonValue != 0; + } + + case 6: + if (!map._isOutdoors) { + scripts.openGrate(9, 0); + eventsFlag = _buttonValue != 0; + } + break; + case 9: + if (!map._isOutdoors) { + scripts.openGrate(6, 0); + eventsFlag = _buttonValue != 0; + } + break; + case 13: + if (!map._isOutdoors) { + scripts.openGrate(1, 1); + eventsFlag = _buttonValue != 0; + } break; default: break; } + if (eventsFlag) { + scripts.checkEvents(); + if (_vm->shouldQuit()) + return; + } + } + + switch (_buttonValue) { + case Common::KEYCODE_TAB: + // Stop mosters doing any movement + _vm->_moveMonsters = false; + warning("TODO: showControlPanel"); + break; + + case Common::KEYCODE_SPACE: + case Common::KEYCODE_w: + // Wait one turn + chargeStep(); + moveMonsters(); + _upDoorText = false; + _flipDefaultGround = !_flipDefaultGround; + _flipGround = !_flipGround; + + stepTime(); + break; + case Common::KEYCODE_EQUALS: + case Common::KEYCODE_KP_EQUALS: + // Toggle minimap + party._automapOn = !party._automapOn; + break; + default: + break; } } diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index af26611e6d..2e19d2230f 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -33,6 +33,8 @@ namespace Xeen { class XeenEngine; +#define MINIMAP_SIZE 7 + class Interface: public ButtonContainer, public InterfaceMap { private: XeenEngine *_vm; @@ -98,7 +100,7 @@ private: void setMazeBits(); - void updateAutoMap(); + void drawMiniMap(); void chargeStep(); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index bef0511c81..17c49bef80 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1195,7 +1195,7 @@ void Map::load(int mapId) { loadSky(); } -int Map::mazeLookup(const Common::Point &pt, int layerShift) { +int Map::mazeLookup(const Common::Point &pt, int layerShift, int wallMask) { Common::Point pos = pt; int mapId = _vm->_party->_mazeId; @@ -1259,7 +1259,7 @@ int Map::mazeLookup(const Common::Point &pt, int layerShift) { _currentSteppedOn = _mazeData[_mazeDataIndex]._steppedOnTiles[pos.y][pos.x]; } - return (_mazeData[_mazeDataIndex]._wallData[pos.y][pos.x]._data >> layerShift) & 0xF; + return (_mazeData[_mazeDataIndex]._wallData[pos.y][pos.x]._data >> layerShift) & wallMask; } else { _currentSteppedOn = _isOutdoors; diff --git a/engines/xeen/map.h b/engines/xeen/map.h index ae8ad28efd..16ef15cbdb 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -362,7 +362,6 @@ private: int _sideMonsters; bool _stepped; int _mazeDataIndex; - bool _currentSteppedOn; void loadEvents(int mapId); public: @@ -387,12 +386,13 @@ public: MazeWallLayers _currentWall; int _currentTile; int _currentSurfaceId; + bool _currentSteppedOn; public: Map(XeenEngine *vm); void load(int mapId); - int mazeLookup(const Common::Point &pt, int layerShift); + int mazeLookup(const Common::Point &pt, int layerShift, int wallMask = 0xf); void cellFlagLookup(const Common::Point &pt); @@ -404,6 +404,8 @@ public: MazeData mazeData() { return _mazeData[0]; } + MazeData mazeDataCurrent() { return _mazeData[_mazeDataIndex]; } + void loadSky(); }; -- cgit v1.2.3 From 1f312098ade02210345a5adffcc2dd531d24ee7f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 19 Jan 2015 16:20:40 -0500 Subject: XEEN: Minor minimap fixes --- engines/xeen/interface.cpp | 28 ++++++++++++++++------------ engines/xeen/map.cpp | 16 ++++++++-------- engines/xeen/map.h | 1 + 3 files changed, 25 insertions(+), 20 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index bcb406dcbe..c017514012 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -1115,7 +1115,7 @@ void Interface::setMazeBits() { break; } - _thinWall = (_vm->_map->_currentWall._data != 0x8888) && _wo[27]; + _thinWall = (_vm->_map->_currentWall._data != INVALID_CELL) && _wo[27]; switch (_vm->_map->getCell(8) - 1) { case 1: @@ -2315,9 +2315,13 @@ void Interface::drawMiniMap() { Screen &screen = *_vm->_screen; Window &window1 = screen._windows[1]; - if (screen._windows[2]._enabled || screen._windows[10]._enabled || - (!party._automapOn && !party._wizardEyeActive)) + if (screen._windows[2]._enabled || screen._windows[10]._enabled) return; + if (!party._automapOn && !party._wizardEyeActive) { + // Draw the Might & Magic logo + _globalSprites.draw(window1, 5, Common::Point(232, 9)); + return; + } int v, frame; int frame2 = _overallFrame * 2; @@ -2365,9 +2369,13 @@ void Interface::drawMiniMap() { } } } + + // Draw the direction arrow + _globalSprites.draw(window1, party._mazeDirection + 1, + Common::Point(267, 36)); } else { frame2 = (frame2 + 2) % 8; - + party._wizardEyeActive = true; //**DEBUG** // First draw cell back for positions in the map that have been revealed for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { @@ -2375,7 +2383,7 @@ void Interface::drawMiniMap() { Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), 0, 0xffff); - if (v != 0xffff && (map._currentSteppedOn || party._wizardEyeActive)) { + if (v != INVALID_CELL && (map._currentSteppedOn || party._wizardEyeActive)) { map._tileSprites.draw(window1, 0, Common::Point(xp, yp)); } } @@ -2396,7 +2404,7 @@ void Interface::drawMiniMap() { } } } - + v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0); if (v != 0xffff && !map._currentSurfaceId && (map._currentSteppedOn || party._wizardEyeActive)) { @@ -2548,7 +2556,7 @@ void Interface::drawMiniMap() { for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, ++xDiff, xp += 10) { if (colNum == 4 && rowNum == 4) { - // Center of the minimap + // Center of the minimap. Draw the direction arrow _globalSprites.draw(window1, party._mazeDirection + 1, Common::Point(272, 40)); } @@ -2673,11 +2681,7 @@ void Interface::drawMiniMap() { } } - if (map._isOutdoors) { - _globalSprites.draw(window1, party._mazeDirection + 1, - Common::Point(267, 36)); - } - + // Draw outer rectangle around the automap _globalSprites.draw(window1, 6, Common::Point(223, 3)); party._wizardEyeActive = eyeActive; } diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 17c49bef80..2bc610721a 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1225,7 +1225,7 @@ int Map::mazeLookup(const Common::Point &pt, int layerShift, int wallMask) { } else { // No map, so reached outside indoor area or outer space outdoors _currentSteppedOn = true; - return _isOutdoors ? SURFTYPE_SPACE : 0x8888; + return _isOutdoors ? SURFTYPE_SPACE : INVALID_CELL; } } @@ -1263,7 +1263,7 @@ int Map::mazeLookup(const Common::Point &pt, int layerShift, int wallMask) { } else { _currentSteppedOn = _isOutdoors; - return _isOutdoors ? SURFTYPE_SPACE : 0x8888; + return _isOutdoors ? SURFTYPE_SPACE : INVALID_CELL; } } @@ -1382,8 +1382,8 @@ int Map::getCell(int idx) { } else { _currentSurfaceId = (mapId >= 25 && mapId <= 27) ? 7 : 0; } - _currentWall._data = 0x8888; - return 0x8888; + _currentWall._data = INVALID_CELL; + return INVALID_CELL; } _mazeDataIndex = 0; @@ -1416,8 +1416,8 @@ int Map::getCell(int idx) { _currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT; } - _currentWall._data = 0x8888; - return 0x8888; + _currentWall._data = INVALID_CELL; + return INVALID_CELL; } _mazeDataIndex = 0; @@ -1452,8 +1452,8 @@ int Map::getCell(int idx) { _currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT; } - _currentWall._data = 0x8888; - return 0x8888; + _currentWall._data = INVALID_CELL; + return INVALID_CELL; } } diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 16ef15cbdb..9b19b3a53a 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -35,6 +35,7 @@ namespace Xeen { #define MAP_WIDTH 16 #define MAP_HEIGHT 16 #define TOTAL_SURFACES 16 +#define INVALID_CELL 0x8888 class XeenEngine; -- cgit v1.2.3 From e966feff5ec36cd2f58cafcf1870937aa10bd86f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 19 Jan 2015 18:42:40 -0500 Subject: XEEN: Implemented movement code --- engines/xeen/dialogs.cpp | 6 +- engines/xeen/interface.cpp | 237 +++++++++++++++++++++++++++++++++++++++++++-- engines/xeen/interface.h | 2 + 3 files changed, 235 insertions(+), 10 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index d1662aeb68..b25a8e13c0 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -69,10 +69,10 @@ bool ButtonContainer::checkEvents(XeenEngine *vm) { } else if (events.isKeyPending()) { Common::KeyState keyState; events.getKey(keyState); - if (keyState.ascii >= 32 && keyState.ascii <= 127) { - _buttonValue = keyState.ascii; + + _buttonValue = keyState.keycode | (keyState.flags << 8); + if (_buttonValue) return true; - } } return false; diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index c017514012..b6e368e2e1 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -801,13 +801,13 @@ void Interface::setMainButtons() { addButton(Common::Rect(235, 117, 259, 137), 77, &_iconSprites); addButton(Common::Rect(260, 117, 284, 137), 73, &_iconSprites); addButton(Common::Rect(286, 117, 310, 137), 81, &_iconSprites); - addButton(Common::Rect(109, 137, 122, 147), 9, &_iconSprites); - addButton(Common::Rect(235, 148, 259, 168), 240, &_iconSprites); - addButton(Common::Rect(260, 148, 284, 168), 242, &_iconSprites); - addButton(Common::Rect(286, 148, 310, 168), 241, &_iconSprites); - addButton(Common::Rect(235, 169, 259, 189), 176, &_iconSprites); - addButton(Common::Rect(260, 169, 284, 189), 243, &_iconSprites); - addButton(Common::Rect(286, 169, 310, 189), 177, &_iconSprites); + addButton(Common::Rect(109, 137, 122, 147), Common::KEYCODE_TAB, &_iconSprites); + addButton(Common::Rect(235, 148, 259, 168), Common::KEYCODE_LEFT, &_iconSprites); + addButton(Common::Rect(260, 148, 284, 168), Common::KEYCODE_UP, &_iconSprites); + addButton(Common::Rect(286, 148, 310, 168), Common::KEYCODE_RIGHT, &_iconSprites); + addButton(Common::Rect(235, 169, 259, 189), (Common::KBD_CTRL << 16) |Common::KEYCODE_LEFT, &_iconSprites); + addButton(Common::Rect(260, 169, 284, 189), Common::KEYCODE_DOWN, &_iconSprites); + addButton(Common::Rect(286, 169, 310, 189), (Common::KBD_CTRL << 16) | Common::KEYCODE_RIGHT, &_iconSprites); addButton(Common::Rect(236, 11, 308, 69), Common::KEYCODE_EQUALS, &_iconSprites, false); addButton(Common::Rect(239, 27, 312, 37), 49, &_iconSprites, false); addButton(Common::Rect(239, 37, 312, 47), 50, &_iconSprites, false); @@ -2768,6 +2768,131 @@ void Interface::perform() { stepTime(); break; + + case (Common::KBD_CTRL << 16) | Common::KEYCODE_LEFT: + case Common::KEYCODE_KP4: + if (checkMoveDirection((Common::KBD_CTRL << 16) | Common::KEYCODE_LEFT)) { + switch (party._mazeDirection) { + case DIR_NORTH: + --party._mazePosition.x; + break; + case DIR_SOUTH: + ++party._mazePosition.x; + break; + case DIR_EAST: + ++party._mazePosition.y; + break; + case DIR_WEST: + --party._mazePosition.y; + break; + default: + break; + } + + chargeStep(); + _isAnimReset = true; + party._mazeDirection = (Direction)((int)party._mazeDirection & 3); + _flipSky = !_flipSky; + stepTime(); + } + break; + + case (Common::KBD_CTRL << 16) | Common::KEYCODE_RIGHT: + case Common::KEYCODE_KP6: + if (checkMoveDirection((Common::KBD_CTRL << 16) | Common::KEYCODE_RIGHT)) { + switch (party._mazeDirection) { + case DIR_NORTH: + ++party._mazePosition.x; + break; + case DIR_SOUTH: + --party._mazePosition.x; + break; + case DIR_EAST: + --party._mazePosition.y; + break; + case DIR_WEST: + ++party._mazePosition.y; + break; + default: + break; + } + + chargeStep(); + _isAnimReset = true; + party._mazeDirection = (Direction)((int)party._mazeDirection & 3); + _flipSky = !_flipSky; + stepTime(); + } + break; + + case Common::KEYCODE_LEFT: + case Common::KEYCODE_KP7: + party._mazeDirection = (Direction)((int)party._mazeDirection - 1); + _isAnimReset = true; + party._mazeDirection = (Direction)((int)party._mazeDirection & 3); + _flipSky = !_flipSky; + stepTime(); + break; + + case Common::KEYCODE_RIGHT: + case Common::KEYCODE_KP9: + party._mazeDirection = (Direction)((int)party._mazeDirection + 1); + _isAnimReset = true; + party._mazeDirection = (Direction)((int)party._mazeDirection & 3); + _flipSky = !_flipSky; + stepTime(); + break; + + case Common::KEYCODE_UP: + case Common::KEYCODE_KP8: + if (checkMoveDirection(Common::KEYCODE_UP)) { + switch (party._mazeDirection) { + case DIR_NORTH: + ++party._mazePosition.y; + break; + case DIR_SOUTH: + --party._mazePosition.y; + break; + case DIR_EAST: + ++party._mazePosition.x; + break; + case DIR_WEST: + --party._mazePosition.x; + break; + default: + break; + } + + chargeStep(); + stepTime(); + } + break; + + case Common::KEYCODE_DOWN: + case Common::KEYCODE_KP2: + if (checkMoveDirection(Common::KEYCODE_DOWN)) { + switch (party._mazeDirection) { + case DIR_NORTH: + --party._mazePosition.y; + break; + case DIR_SOUTH: + ++party._mazePosition.y; + break; + case DIR_EAST: + --party._mazePosition.x; + break; + case DIR_WEST: + ++party._mazePosition.x; + break; + default: + break; + } + + chargeStep(); + stepTime(); + } + break; + case Common::KEYCODE_EQUALS: case Common::KEYCODE_KP_EQUALS: // Toggle minimap @@ -2814,4 +2939,102 @@ void Interface::doStepCode() { // TODO } +bool Interface::checkMoveDirection(int key) { + Map &map = *_vm->_map; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + Direction dir = party._mazeDirection; + + switch (_buttonValue) { + case (Common::KBD_CTRL << 16) | Common::KEYCODE_LEFT: + party._mazeDirection = (party._mazeDirection == DIR_NORTH) ? DIR_WEST : + (Direction)(party._mazeDirection - 1); + break; + case (Common::KBD_CTRL << 16) | Common::KEYCODE_RIGHT: + party._mazeDirection = (party._mazeDirection == DIR_WEST) ? DIR_NORTH : + (Direction)(party._mazeDirection + 1); + break; + case Common::KEYCODE_DOWN: + party._mazeDirection = (party._mazeDirection == DIR_NORTH) ? DIR_SOUTH : DIR_NORTH; + break; + default: + break; + } + + map.getCell(7); + int startSurfaceId = map._currentSurfaceId; + int surfaceId; + + if (map._isOutdoors) { + party._mazeDirection = dir; + + switch ((int)map._currentWall._outdoors._surfaceId) { + case 5: + if (_vm->_files->_isDarkCc) + goto check; + + // Deliberate FAll-through + case 0: + case 2: + case 4: + case 8: + case 11: + case 13: + case 14: + surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; + if (surfaceId == SURFTYPE_WATER) { + if (party.checkSkill(SWIMMING) || party._walkOnWaterActive) + return true; + } else if (surfaceId == SURFTYPE_DWATER) { + if (party._walkOnWaterActive) + return true; + } + else if (surfaceId != SURFTYPE_SPACE) { + return true; + } + + sound.playFX(21); + return false; + + case 1: + case 7: + case 9: + case 10: + case 12: + check: + if (party.checkSkill(MOUNTAINEER)) + return true; + + sound.playFX(21); + return false; + + default: + break; + } + } else { + int surfaceId = map.getCell(2); + if (surfaceId >= map.mazeData()._difficulties._wallNoPass) { + party._mazeDirection = dir; + } else { + party._mazeDirection = dir; + + if (surfaceId == SURFTYPE_SWAMP || party.checkSkill(SWIMMING) || + party._walkOnWaterActive) { + sound.playFX(46); + return false; + } else { + if (_buttonValue == 242 && _wo[107]) { + _vm->_openDoor = true; + sound.playFX(47); + draw3d(true); + _vm->_openDoor = false; + } + return true; + } + } + } + + return true; +} + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 2e19d2230f..8497cc6c26 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -107,6 +107,8 @@ private: void stepTime(); void doStepCode(); + + bool checkMoveDirection(int key); public: Interface(XeenEngine *vm); -- cgit v1.2.3 From ebc155ac0abc5eda87541cf56f46b7d18d9903b3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 19 Jan 2015 18:51:29 -0500 Subject: XEEN: Replaced UI button values with KeyCode constants --- engines/xeen/interface.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index b6e368e2e1..708e8b7568 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -792,15 +792,15 @@ void Interface::moveMonsters() { void Interface::setMainButtons() { clearButtons(); - addButton(Common::Rect(235, 75, 259, 95), 83, &_iconSprites); - addButton(Common::Rect(260, 75, 284, 95), 67, &_iconSprites); - addButton(Common::Rect(286, 75, 310, 95), 82, &_iconSprites); - addButton(Common::Rect(235, 96, 259, 116), 66, &_iconSprites); - addButton(Common::Rect(260, 96, 284, 116), 68, &_iconSprites); - addButton(Common::Rect(286, 96, 310, 116), 86, &_iconSprites); - addButton(Common::Rect(235, 117, 259, 137), 77, &_iconSprites); - addButton(Common::Rect(260, 117, 284, 137), 73, &_iconSprites); - addButton(Common::Rect(286, 117, 310, 137), 81, &_iconSprites); + addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_s, &_iconSprites); + addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_c, &_iconSprites); + addButton(Common::Rect(286, 75, 310, 95), Common::KEYCODE_r, &_iconSprites); + addButton(Common::Rect(235, 96, 259, 116), Common::KEYCODE_b, &_iconSprites); + addButton(Common::Rect(260, 96, 284, 116), Common::KEYCODE_d, &_iconSprites); + addButton(Common::Rect(286, 96, 310, 116), Common::KEYCODE_v, &_iconSprites); + addButton(Common::Rect(235, 117, 259, 137), Common::KEYCODE_m, &_iconSprites); + addButton(Common::Rect(260, 117, 284, 137), Common::KEYCODE_i, &_iconSprites); + addButton(Common::Rect(286, 117, 310, 137), Common::KEYCODE_q, &_iconSprites); addButton(Common::Rect(109, 137, 122, 147), Common::KEYCODE_TAB, &_iconSprites); addButton(Common::Rect(235, 148, 259, 168), Common::KEYCODE_LEFT, &_iconSprites); addButton(Common::Rect(260, 148, 284, 168), Common::KEYCODE_UP, &_iconSprites); @@ -809,9 +809,9 @@ void Interface::setMainButtons() { addButton(Common::Rect(260, 169, 284, 189), Common::KEYCODE_DOWN, &_iconSprites); addButton(Common::Rect(286, 169, 310, 189), (Common::KBD_CTRL << 16) | Common::KEYCODE_RIGHT, &_iconSprites); addButton(Common::Rect(236, 11, 308, 69), Common::KEYCODE_EQUALS, &_iconSprites, false); - addButton(Common::Rect(239, 27, 312, 37), 49, &_iconSprites, false); - addButton(Common::Rect(239, 37, 312, 47), 50, &_iconSprites, false); - addButton(Common::Rect(239, 47, 312, 57), 51, &_iconSprites, false); + addButton(Common::Rect(239, 27, 312, 37), Common::KEYCODE_1, &_iconSprites, false); + addButton(Common::Rect(239, 37, 312, 47), Common::KEYCODE_2, &_iconSprites, false); + addButton(Common::Rect(239, 47, 312, 57), Common::KEYCODE_3, &_iconSprites, false); } void Interface::setMazeBits() { -- cgit v1.2.3 From dc8592a9128ed389ba9d466bac96bc15609d3eef Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 19 Jan 2015 19:28:38 -0500 Subject: XEEN: Fix loading of wall types --- engines/xeen/map.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 2bc610721a..bf03905818 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1118,12 +1118,14 @@ void Map::load(int mapId) { for (int i = 0; i < TOTAL_SURFACES; ++i) _wallSprites._surfaces[i].clear(); - Common::String fwlName = Common::String::format("%s.til", - TERRAIN_TYPES[_mazeData[0]._wallKind]); - _wallSprites._fwl1.load(fwlName); - _wallSprites._fwl2.load(fwlName); - _wallSprites._fwl3.load(fwlName); - _wallSprites._fwl4.load(fwlName); + _wallSprites._fwl1.load(Common::String::format("f%s1.fwl", + TERRAIN_TYPES[_mazeData[0]._wallKind])); + _wallSprites._fwl2.load(Common::String::format("f%s2.fwl", + TERRAIN_TYPES[_mazeData[0]._wallKind])); + _wallSprites._fwl3.load(Common::String::format("f%s3.fwl", + TERRAIN_TYPES[_mazeData[0]._wallKind])); + _wallSprites._fwl4.load(Common::String::format("f%s4.fwl", + TERRAIN_TYPES[_mazeData[0]._wallKind])); _wallSprites._swl.load(Common::String::format("s%s.swl", TERRAIN_TYPES[_mazeData[0]._wallKind])); @@ -1182,7 +1184,7 @@ void Map::load(int mapId) { indoorList._ground._sprites = &_groundSprites; - // Down show horizon for certain maps + // Don't show horizon for certain maps if (_vm->_files->_isDarkCc) { if ((mapId >= 89 && mapId <= 112) || mapId == 128 || mapId == 129) indoorList._horizon._sprites = nullptr; -- cgit v1.2.3 From a1fb631fe3fc16b534dab2e9074bf8a56d16bdc3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 19 Jan 2015 22:38:20 -0500 Subject: XEEN: Fix resetting sprites on ground tiles when drawing --- engines/xeen/interface_map.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 1f927112b8..5b1d4e995e 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -1112,8 +1112,8 @@ void InterfaceMap::drawIndoors() { map.getCell(DRAW_NUMBERS[cellIndex]); DrawStruct &drawStruct = _indoorList._groundTiles[cellIndex]; - if (!map._surfaceSprites[map._currentSurfaceId].empty()) - drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId]; + SpriteResource &sprites = map._surfaceSprites[map._currentSurfaceId]; + drawStruct._sprites = sprites.empty() ? (SpriteResource *)nullptr : &sprites; surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; if (surfaceId == SURFTYPE_WATER || surfaceId == SURFTYPE_LAVA || -- cgit v1.2.3 From 8cd2e5ad9234b148ad5a960d44422ae982e9091f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 19 Jan 2015 22:38:33 -0500 Subject: XEEN: Further work on sprite scaling --- engines/xeen/sprites.cpp | 2 +- engines/xeen/xsurface.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 1d9a5c8abf..62074ed565 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -230,7 +230,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, int flags, int scale) const { - scale = 0; // ***DEBUG*** + if (scale == 0) { drawOffset(dest, _index[frame]._offset1, destPos, flags); if (_index[frame]._offset2) diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp index b01ade17df..7060a6326a 100644 --- a/engines/xeen/xsurface.cpp +++ b/engines/xeen/xsurface.cpp @@ -112,8 +112,8 @@ void XSurface::transBlitTo(XSurface &dest, const Common::Point &destPos, } } while (++distIndex < highestDim); - destX -= distXCount / 2; - destY -= distYCount - 1; + destX += (this->w - distXCount) / 2; + destY += (this->h - distYCount) / 2; } // Start of draw logic for scaled sprites -- cgit v1.2.3 From d32c90eee9c683b4d62656d3e13d888c16aad9c3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 19 Jan 2015 23:18:44 -0500 Subject: XEEN: Some minimap drawing fixes --- engines/xeen/interface.cpp | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 708e8b7568..67f6363ce9 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -2376,7 +2376,7 @@ void Interface::drawMiniMap() { } else { frame2 = (frame2 + 2) % 8; party._wizardEyeActive = true; //**DEBUG** - // First draw cell back for positions in the map that have been revealed + // First draw the default surface bases for each cell to show for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { v = map.mazeLookup( @@ -2388,59 +2388,58 @@ void Interface::drawMiniMap() { } } } - - // Draw tiles based on the surface for each revelaed tile + + // Draw correct surface bases for revealed tiles for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { v = map.mazeLookup( Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), 0, 0xffff); + int surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; - if (v != 0xffff && !map._currentSurfaceId && + if (v != INVALID_CELL && map._currentSurfaceId && (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, - map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, - Common::Point(xp, yp)); + map._tileSprites.draw(window1, surfaceId + 36, Common::Point(xp, yp)); } } } v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0); - if (v != 0xffff && !map._currentSurfaceId && + if (v != INVALID_CELL && map._currentSurfaceId && (map._currentSteppedOn || party._wizardEyeActive)) { map._tileSprites.draw(window1, map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, Common::Point(232, 9)); } - - // Right edge - for (int rowNum = 0, yp = 242, yDiff = -3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) { + + // Handle drawing surface sprites partially clipped at the left edge + for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) { v = map.mazeLookup( Common::Point(party._mazePosition.x - 4, party._mazePosition.y + yDiff), 0, 0xffff); - if (v != 0xffff && !map._currentSurfaceId && - (map._currentSteppedOn || party._wizardEyeActive)) { + if (v != INVALID_CELL && map._currentSurfaceId && + (map._currentSteppedOn || party._wizardEyeActive)) { map._tileSprites.draw(window1, map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, Common::Point(232, yp)); } } - // Top edge - for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, --xDiff, xp += 8) { + // Handle drawing surface sprites partially clipped at the top edge + for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, ++xDiff, xp += 8) { v = map.mazeLookup( Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + 4), 0, 0xffff); - if (v != 0xffff && !map._currentSurfaceId && + if (v != INVALID_CELL && map._currentSurfaceId && (map._currentSteppedOn || party._wizardEyeActive)) { map._tileSprites.draw(window1, map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, Common::Point(xp, 9)); } } - + // for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE; ++idx, --xDiff, xp += 10, yp -= 8) { @@ -2552,7 +2551,7 @@ void Interface::drawMiniMap() { // for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; - ++rowNum, --yDiff, yp -= 8) { + ++rowNum, --yDiff, yp += 8) { for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, ++xDiff, xp += 10) { if (colNum == 4 && rowNum == 4) { @@ -2673,8 +2672,8 @@ void Interface::drawMiniMap() { Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), 0, 0xffff); - if (v != 0xffff && !map._currentSurfaceId && - (map._currentSteppedOn || party._wizardEyeActive)) { + if (v != INVALID_CELL && !map._currentSurfaceId && + (map._currentSteppedOn || party._wizardEyeActive)) { map._tileSprites.draw(window1, 1, Common::Point(xp, yp)); } } @@ -2988,8 +2987,7 @@ bool Interface::checkMoveDirection(int key) { } else if (surfaceId == SURFTYPE_DWATER) { if (party._walkOnWaterActive) return true; - } - else if (surfaceId != SURFTYPE_SPACE) { + } else if (surfaceId != SURFTYPE_SPACE) { return true; } -- cgit v1.2.3 From aab62d606ec726b6363f067cee17c284d8b396d1 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 19 Jan 2015 23:57:13 -0500 Subject: XEEN: More minimap fixes --- engines/xeen/interface.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 67f6363ce9..16ded9ec19 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -2375,7 +2375,7 @@ void Interface::drawMiniMap() { Common::Point(267, 36)); } else { frame2 = (frame2 + 2) % 8; - party._wizardEyeActive = true; //**DEBUG** + // First draw the default surface bases for each cell to show for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { @@ -2442,7 +2442,7 @@ void Interface::drawMiniMap() { // for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE; - ++idx, --xDiff, xp += 10, yp -= 8) { + ++idx, ++xDiff, xp += 10, yp -= 8) { v = map.mazeLookup( Common::Point(party._mazePosition.x - 4, party._mazePosition.y - 3 + idx), 12, 0xffff); @@ -2549,7 +2549,7 @@ void Interface::drawMiniMap() { map._tileSprites.draw(window1, frame, Common::Point(xp, 4)); } - // + // Draw the front/back walls of cells in the minimap for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) { for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; @@ -2665,15 +2665,14 @@ void Interface::drawMiniMap() { } } - // Final loop + // Draw the top of blocked/wall cells on the map for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { v = map.mazeLookup( Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), 0, 0xffff); - if (v != INVALID_CELL && !map._currentSurfaceId && - (map._currentSteppedOn || party._wizardEyeActive)) { + if (v == INVALID_CELL || (!map._currentSteppedOn && !party._wizardEyeActive)) { map._tileSprites.draw(window1, 1, Common::Point(xp, yp)); } } -- cgit v1.2.3 From 2427f203ee9b98d639ecb0bde6aad17c35875a43 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 20 Jan 2015 08:20:07 -0500 Subject: XEEN: Implemented handleLight --- engines/xeen/interface.cpp | 8 +++++++- engines/xeen/interface.h | 3 ++- engines/xeen/map.cpp | 7 +++---- engines/xeen/map.h | 1 - engines/xeen/party.cpp | 17 +++++++++++++++++ engines/xeen/party.h | 3 +++ 6 files changed, 32 insertions(+), 7 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 16ded9ec19..e117813756 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -743,6 +743,10 @@ void Interface::draw3d(bool updateFlag) { // TODO: more stuff + _vm->_party->_stepped = false; + if (_vm->_mode == MODE_9) { + // TODO + } events.wait(2); } @@ -933,6 +937,8 @@ void Interface::setMazeBits() { break; } + _vm->_party->handleLight(); + switch (_vm->_map->getCell(3) - 1) { case 1: ++_wo[73]; @@ -3015,7 +3021,7 @@ bool Interface::checkMoveDirection(int key) { } else { party._mazeDirection = dir; - if (surfaceId == SURFTYPE_SWAMP || party.checkSkill(SWIMMING) || + if (startSurfaceId == SURFTYPE_SWAMP || party.checkSkill(SWIMMING) || party._walkOnWaterActive) { sound.playFX(46); return false; diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 8497cc6c26..9634788df3 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -68,7 +68,6 @@ private: bool _buttonsLoaded; Common::String _interfaceText; int _hiliteChar; - int _intrIndex1; bool _flag1; int _animCounter; bool _isAnimReset; @@ -109,6 +108,8 @@ private: void doStepCode(); bool checkMoveDirection(int key); +public: + int _intrIndex1; public: Interface(XeenEngine *vm); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index bf03905818..655412543b 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -544,8 +544,8 @@ MazeData::MazeData() { for (int y = 0; y < MAP_HEIGHT; ++y) { for (int x = 0; x < MAP_WIDTH; ++x) _wallData[y][x]._data = 0; - Common::fill(&_seenTiles[y][0], &_seenTiles[y][MAP_WIDTH], 0); - Common::fill(&_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH], 0); + Common::fill(&_seenTiles[y][0], &_seenTiles[y][MAP_WIDTH], false); + Common::fill(&_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH], false); _wallTypes[y] = 0; _surfaceTypes[y] = 0; } @@ -859,7 +859,6 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { _sideMonsters = 0; _sidePictures = 0; _isOutdoors = false; - _stepped = false; _mazeDataIndex = 0; _currentSteppedOn = false; _currentSurfaceId = 0; @@ -886,7 +885,7 @@ void Map::load(int mapId) { PleaseWait::show(_vm); } - _stepped = true; + _vm->_party->_stepped = true; _vm->_party->_mazeId = mapId; _vm->_events->clearEvents(); diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 9b19b3a53a..80c46dd607 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -361,7 +361,6 @@ private: int _sidePictures; int _sideObjects; int _sideMonsters; - bool _stepped; int _mazeDataIndex; void loadEvents(int mapId); diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 4571bbe518..3736869eb4 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -231,6 +231,7 @@ Party::Party(XeenEngine *vm): _vm(vm) { _partyDead = false; _newDay = false; _isNight = false; + _stepped = false; } void Party::synchronize(Common::Serializer &s) { @@ -543,5 +544,21 @@ void Party::resetTemps() { _blessedActive = false; } +void Party::handleLight() { + Map &map = *_vm->_map; + + if (_stepped) { + map.cellFlagLookup(_mazePosition); + if (map._currentIsDrain && _lightCount) + --_lightCount; + + if (checkSkill(CARTOGRAPHER)) { + map.mazeDataCurrent()._steppedOnTiles[_mazePosition.y & 15][_mazePosition.x & 15] = true; + } + } + + _vm->_interface->_intrIndex1 = _lightCount || + (map.mazeData()._mazeFlags2 & FLAG_IS_DARK) == 0 ? 4 : 0; +} } // End of namespace Xeen diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 8db52df1a6..e2180e535d 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -212,6 +212,7 @@ public: bool _partyDead; bool _newDay; bool _isNight; + bool _stepped; public: Party(XeenEngine *vm); @@ -228,6 +229,8 @@ public: void addTime(int numMinutes); void resetTemps(); + + void handleLight(); }; } // End of namespace Xeen -- cgit v1.2.3 From 8b4d25d415bff87cfcc00fdf827139dda2fa4014 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 20 Jan 2015 08:46:27 -0500 Subject: XEEN: Implemented doStepCode --- engines/xeen/combat.h | 18 ++++++++++++ engines/xeen/interface.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++++-- engines/xeen/interface.h | 2 ++ engines/xeen/map.cpp | 6 +++- engines/xeen/map.h | 21 ++------------ engines/xeen/party.cpp | 2 ++ engines/xeen/party.h | 3 ++ engines/xeen/scripts.cpp | 1 + engines/xeen/scripts.h | 1 - engines/xeen/xeen.cpp | 1 - engines/xeen/xeen.h | 1 - 11 files changed, 103 insertions(+), 24 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index c64741b59e..8e54353212 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -27,6 +27,24 @@ namespace Xeen { +enum DamageType { + DT_PHYSICAL = 0, DT_1 = 1, DT_FIRE = 2, DT_ELECTRICAL = 3, + DT_COLD = 4, DT_POISON = 5, DT_ENERGY = 6, DT_SLEEP = 7, + DT_FINGEROFDEATH = 8, DT_HOLYWORD = 9, DT_MASS_DISTORTION = 10, + DT_UNDED = 11, DT_BEASTMASTER = 12, DT_DRAGONSLEEP = 13, + DT_GOLEMSTOPPER = 14, DT_HYPNOTIZE = 15, DT_INSECT_SPRAY = 16, + DT_POISON_VALLEY = 17, DT_MAGIC_ARROW = 18 +}; + +enum SpecialAttack { + SA_NONE = 0, SA_MAGIC = 1, SA_FIRE = 2, SA_ELEC = 3, SA_COLD = 4, + SA_POISON = 5, SA_ENERGY = 6, SA_DISEASE = 7, SA_INSANE = 8, + SA_SLEEP = 9, SA_CURSEITEM = 10, SA_INLOVE = 11, SA_DRAINSP = 12, + SA_CURSE = 13, SA_PARALYZE = 14, SA_UNCONSCIOUS = 15, + SA_CONFUSE = 16, SA_BREAKWEAPON = 17, SA_WEAKEN = 18, + SA_ERADICATE = 19, SA_AGING = 20, SA_DEATH = 21, SA_STONE = 22 +}; + class XeenEngine; class Combat { diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index e117813756..cd96f05ab9 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -541,6 +541,7 @@ void Interface::draw3d(bool updateFlag) { Combat &combat = *_vm->_combat; EventsManager &events = *_vm->_events; Map &map = *_vm->_map; + Party &party = *_vm->_party; Screen &screen = *_vm->_screen; if (screen._windows[11]._enabled) @@ -724,11 +725,11 @@ void Interface::draw3d(bool updateFlag) { animate3d(); drawMiniMap(); - if (_vm->_falling == 1) { + if (party._falling == 1) { error("TODO: Indoor falling"); } - if (_vm->_falling == 2) { + if (party._falling == 2) { screen.saveBackground(1); } @@ -2940,6 +2941,72 @@ void Interface::stepTime() { } void Interface::doStepCode() { + Map &map = *_vm->_map; + Party &party = *_vm->_party; + int damage = 0; + + party._stepped = true; + _upDoorText = false; + + map.getCell(2); + int surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; + + switch (surfaceId) { + case SURFTYPE_SPACE: + // Wheeze.. can't breathe in space! Explosive decompression, here we come + party._partyDead = true; + break; + case SURFTYPE_LAVA: + // It burns, it burns! + damage = 100; + party._damageType = DT_FIRE; + break; + case SURFTYPE_SKY: + // We can fly, we can.. oh wait, we can't! + damage = 100; + party._damageType = DT_PHYSICAL; + party._falling = true; + break; + case SURFTYPE_DESERT: + // Without navigation skills, simulate getting lost by adding extra time + if (map._isOutdoors && !party.checkSkill(NAVIGATOR)) + party.addTime(170); + break; + case SURFTYPE_CLOUD: + if (!party._levitateActive) { + party._damageType = DT_PHYSICAL; + party._falling = true; + damage = 100; + } + break; + default: + break; + } + + if (_vm->_files->_isDarkCc && party._gameFlags[374]) { + party._falling = false; + } else { + if (party._falling) + doFalling(); + + if ((party._mazePosition.x & 16) || (party._mazePosition.y & 16)) { + map.getNewMaze(); + } + + if (damage) { + _flipGround = !_flipGround; + draw3d(true); + + warning("TODO: apply damage"); + + _flipGround = !_flipGround; + } else if (party._partyDead) { + draw3d(true); + } + } +} + +void Interface::doFalling() { // TODO } diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 9634788df3..4cd40b9d4f 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -129,6 +129,8 @@ public: void charIconsPrint(bool updateFlag); + void doFalling(); + void perform(); }; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 655412543b..7e1f8546ea 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -877,7 +877,7 @@ void Map::load(int mapId) { IndoorDrawList &indoorList = _vm->_interface->_indoorList; OutdoorDrawList &outdoorList = _vm->_interface->_outdoorList; - if (_vm->_falling) { + if (_vm->_party->_falling) { Window &w = screen._windows[9]; w.open(); w.writeString(OOPS); @@ -1500,4 +1500,8 @@ void Map::loadSky() { ? "sky.sky" : "night.sky"); } +void Map::getNewMaze() { + // TODO +} + } // End of namespace Xeen diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 80c46dd607..32418257f4 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -26,6 +26,7 @@ #include "common/stream.h" #include "common/array.h" #include "common/rect.h" +#include "xeen/combat.h" #include "xeen/party.h" #include "xeen/scripts.h" #include "xeen/sprites.h" @@ -39,24 +40,6 @@ namespace Xeen { class XeenEngine; -enum DamageType { - DT_PHYSICAL = 0, DT_1 = 1, DT_FIRE = 2, DT_ELECTRICAL = 3, - DT_COLD = 4, DT_POISON = 5, DT_ENERGY = 6, DT_SLEEP = 7, - DT_FINGEROFDEATH = 8, DT_HOLYWORD = 9, DT_MASS_DISTORTION = 10, - DT_UNDED = 11, DT_BEASTMASTER = 12, DT_DRAGONSLEEP = 13, - DT_GOLEMSTOPPER = 14, DT_HYPNOTIZE = 15, DT_INSECT_SPRAY = 16, - DT_POISON_VALLEY = 17, DT_MAGIC_ARROW = 18 -}; - -enum SpecialAttack { - SA_NONE = 0, SA_MAGIC = 1, SA_FIRE = 2, SA_ELEC = 3, SA_COLD = 4, - SA_POISON = 5, SA_ENERGY = 6, SA_DISEASE = 7, SA_INSANE = 8, - SA_SLEEP = 9, SA_CURSEITEM = 10, SA_INLOVE = 11, SA_DRAINSP = 12, - SA_CURSE = 13, SA_PARALYZE = 14, SA_UNCONSCIOUS = 15, - SA_CONFUSE = 16, SA_BREAKWEAPON = 17, SA_WEAKEN = 18, - SA_ERADICATE = 19, SA_AGING = 20, SA_DEATH = 21, SA_STONE = 22 -}; - enum MonsterType { MONSTER_0 = 0, MONSTER_ANIMAL = 1, MONSTER_INSECT = 2, MONSTER_HUMANOID = 3, MONSTER_UNDEAD = 4, MONSTER_GOLEM = 5, @@ -407,6 +390,8 @@ public: MazeData mazeDataCurrent() { return _mazeData[_mazeDataIndex]; } void loadSky(); + + void getNewMaze(); }; } // End of namespace Xeen diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 3736869eb4..d465cc9975 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -232,6 +232,8 @@ Party::Party(XeenEngine *vm): _vm(vm) { _newDay = false; _isNight = false; _stepped = false; + _damageType = DT_PHYSICAL; + _falling = false; } void Party::synchronize(Common::Serializer &s) { diff --git a/engines/xeen/party.h b/engines/xeen/party.h index e2180e535d..c598e8c3f9 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -27,6 +27,7 @@ #include "common/array.h" #include "common/rect.h" #include "common/serializer.h" +#include "xeen/combat.h" #include "xeen/items.h" namespace Xeen { @@ -213,6 +214,8 @@ public: bool _newDay; bool _isNight; bool _stepped; + int _falling; + DamageType _damageType; public: Party(XeenEngine *vm); diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 5a36a32a7e..55388ec343 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -21,6 +21,7 @@ */ #include "xeen/scripts.h" +#include "xeen/party.h" namespace Xeen { diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 4f49018e2b..9974892221 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -27,7 +27,6 @@ #include "common/system.h" #include "common/serializer.h" #include "xeen/files.h" -#include "xeen/party.h" namespace Xeen { diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index e9b4d93de8..38026d0117 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -53,7 +53,6 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _face1State = 0; _face2State = 0; _noDirectionSense = false; - _falling = 0; _moveMonsters = false; _mode = MODE_0; _openDoor = 0; diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 59816b0d91..3e8637476a 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -148,7 +148,6 @@ public: int _face1State; int _face2State; bool _noDirectionSense; - int _falling; bool _moveMonsters; int _openDoor; public: -- cgit v1.2.3 From 5cc3afab7293cdaf2ce339f2527da7ce5ed804fc Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 20 Jan 2015 19:48:44 -0500 Subject: XEEN: Implemented getNewMaze --- engines/xeen/map.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 7e1f8546ea..6b577ebd45 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1501,7 +1501,54 @@ void Map::loadSky() { } void Map::getNewMaze() { - // TODO + Party &party = *_vm->_party; + Common::Point pt = party._mazePosition; + int mapId = party._mazeId; + + // Get the correct map to use from the cached list + _mazeDataIndex = 0; + while (_mazeData[_mazeDataIndex]._mazeId == mapId) + ++_mazeDataIndex; + + // Adjust Y and X to be in the 0-15 range, and on the correct surrounding + // map if either value is < 0 or >= 16 + if (pt.y & 16) { + if (pt.y >= 0) { + pt.y -= 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._north; + } else { + pt.y += 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._south; + } + + if (mapId) { + _mazeDataIndex = 0; + while (_mazeData[_mazeDataIndex]._mazeId == mapId) + ++_mazeDataIndex; + } + } + + if (pt.x & 16) { + if (pt.x >= 0) { + pt.x -= 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._east; + } else { + pt.x += 16; + mapId = _mazeData[_mazeDataIndex]._surroundingMazes._west; + } + + if (mapId) { + _mazeDataIndex = 0; + while (_mazeData[_mazeDataIndex]._mazeId == mapId) + ++_mazeDataIndex; + } + } + + // Save the adjusted (0,0)-(15,15) position and load the given map. + // This will make it the new center, with it's own surrounding mazees loaded + party._mazePosition = pt; + if (mapId) + load(mapId); } } // End of namespace Xeen -- cgit v1.2.3 From 397a10eae5d63d148815386d782fd7b035c195fd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 20 Jan 2015 21:05:15 -0500 Subject: XEEN: Moved setMazeBits to InterfaceMap and fixed some incorrect code in it --- engines/xeen/interface.cpp | 1501 +-------------------------------------- engines/xeen/interface.h | 3 - engines/xeen/interface_map.cpp | 1504 ++++++++++++++++++++++++++++++++++++++++ engines/xeen/interface_map.h | 3 + 4 files changed, 1509 insertions(+), 1502 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index cd96f05ab9..d2fea36872 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -46,7 +46,6 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm( _animCounter = 0; _isAnimReset = false; _tillMove = 0; - _thinWall = false; _overallFrame = 0; _upDoorText = false; _steppingFX = 0; @@ -819,1503 +818,6 @@ void Interface::setMainButtons() { addButton(Common::Rect(239, 47, 312, 57), Common::KEYCODE_3, &_iconSprites, false); } -void Interface::setMazeBits() { - Common::fill(&_wo[0], &_wo[308], 0); - - switch (_vm->_map->getCell(0) - 1) { - case 0: - ++_wo[125]; - break; - case 1: - ++_wo[69]; - break; - case 2: - ++_wo[185]; - break; - case 3: - case 12: - ++_wo[105]; - break; - case 4: - case 7: - ++_wo[25]; - break; - case 5: - ++_wo[225]; - break; - case 6: - ++_wo[205]; - break; - case 8: - ++_wo[145]; - break; - case 9: - ++_wo[305]; - break; - case 10: - ++_wo[245]; - break; - case 11: - ++_wo[165]; - break; - case 13: - ++_wo[265]; - break; - case 14: - ++_wo[285]; - break; - default: - break; - } - - switch (_vm->_map->getCell(1) - 1) { - case 1: - ++_wo[72]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[28]; - break; - default: - break; - } - - switch (_vm->_map->getCell(2) - 1) { - case 0: - ++_wo[127]; - break; - case 1: - ++_wo[71]; - break; - case 2: - ++_wo[187]; - break; - case 3: - case 12: - ++_wo[107]; - break; - case 4: - case 7: - ++_wo[27]; - break; - case 5: - ++_wo[227]; - break; - case 6: - ++_wo[207]; - break; - case 8: - ++_wo[147]; - break; - case 9: - ++_wo[307]; - break; - case 10: - ++_wo[247]; - break; - case 11: - ++_wo[167]; - break; - case 13: - ++_wo[267]; - break; - case 14: - ++_wo[287]; - break; - default: - break; - } - - _vm->_party->handleLight(); - - switch (_vm->_map->getCell(3) - 1) { - case 1: - ++_wo[73]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[29]; - break; - default: - break; - } - - switch (_vm->_map->getCell(4) - 1) { - case 0: - ++_wo[126]; - break; - case 1: - ++_wo[70]; - break; - case 2: - ++_wo[186]; - break; - case 3: - case 12: - ++_wo[106]; - break; - case 4: - case 7: - ++_wo[26]; - break; - case 5: - ++_wo[226]; - break; - case 6: - ++_wo[206]; - case 8: - ++_wo[146]; - break; - case 9: - ++_wo[306]; - break; - case 10: - ++_wo[246]; - break; - break; - case 11: - ++_wo[166]; - break; - case 13: - ++_wo[266]; - break; - case 14: - ++_wo[286]; - break; - default: - break; - } - - switch (_vm->_map->getCell(5) - 1) { - case 0: - ++_wo[122]; - break; - case 1: - ++_wo[64]; - break; - case 2: - ++_wo[182]; - break; - case 3: - case 12: - ++_wo[102]; - break; - case 5: - ++_wo[222]; - break; - case 6: - ++_wo[202]; - break; - case 8: - ++_wo[142]; - break; - case 9: - ++_wo[302]; - break; - case 10: - ++_wo[242]; - break; - case 11: - ++_wo[162]; - break; - case 13: - ++_wo[262]; - break; - case 14: - ++_wo[282]; - break; - default: - break; - } - - switch (_vm->_map->getCell(6) - 1) { - case 1: - ++_wo[67]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[23]; - break; - default: - break; - } - - switch (_vm->_map->getCell(7) - 1) { - case 0: - ++_wo[124]; - break; - case 1: - ++_wo[66]; - break; - case 2: - ++_wo[184]; - break; - case 3: - case 12: - ++_wo[104]; - break; - case 4: - case 7: - ++_wo[22]; - break; - case 5: - ++_wo[224]; - break; - case 6: - ++_wo[204]; - break; - case 8: - ++_wo[144]; - break; - case 9: - ++_wo[304]; - break; - case 10: - ++_wo[244]; - break; - case 11: - ++_wo[164]; - break; - case 13: - ++_wo[264]; - break; - case 14: - ++_wo[284]; - break; - default: - break; - } - - _thinWall = (_vm->_map->_currentWall._data != INVALID_CELL) && _wo[27]; - - switch (_vm->_map->getCell(8) - 1) { - case 1: - ++_wo[68]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[24]; - break; - default: - break; - } - - switch (_vm->_map->getCell(9) - 1) { - case 0: - ++_wo[123]; - break; - case 1: - ++_wo[65]; - break; - case 2: - ++_wo[183]; - break; - case 3: - case 12: - ++_wo[103]; - break; - case 4: - case 7: - ++_wo[21]; - break; - case 5: - ++_wo[223]; - break; - case 6: - ++_wo[203]; - break; - case 8: - ++_wo[143]; - break; - case 9: - ++_wo[3033]; - break; - case 10: - ++_wo[243]; - break; - case 11: - ++_wo[163]; - break; - case 13: - ++_wo[263]; - break; - case 14: - ++_wo[283]; - break; - default: - break; - } - - switch (_vm->_map->getCell(10) - 1) { - case 0: - ++_wo[117]; - break; - case 1: - ++_wo[55]; - break; - case 2: - ++_wo[177]; - break; - case 3: - case 12: - ++_wo[97]; - break; - case 4: - case 7: - ++_wo[11]; - break; - case 5: - ++_wo[217]; - break; - case 6: - ++_wo[197]; - break; - case 8: - ++_wo[137]; - break; - case 9: - ++_wo[297]; - break; - case 10: - ++_wo[237]; - case 11: - ++_wo[157]; - break; - case 13: - ++_wo[257]; - break; - case 14: - ++_wo[277]; - break; - default: - break; - } - - switch (_vm->_map->getCell(11) - 1) { - case 1: - ++_wo[60]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[16]; - break; - default: - break; - } - - switch (_vm->_map->getCell(12) - 1) { - case 0: - ++_wo[118]; - break; - case 1: - ++_wo[56]; - break; - case 2: - ++_wo[178]; - break; - case 3: - case 12: - ++_wo[98]; - break; - case 4: - case 7: - ++_wo[12]; - break; - case 5: - ++_wo[218]; - break; - case 6: - ++_wo[198]; - break; - case 8: - ++_wo[138]; - break; - case 9: - ++_wo[298]; - break; - case 10: - ++_wo[238]; - break; - case 11: - ++_wo[158]; - break; - case 13: - ++_wo[258]; - break; - case 14: - ++_wo[278]; - break; - default: - break; - } - - switch (_vm->_map->getCell(13) - 1) { - case 1: - ++_wo[61]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[17]; - break; - default: - break; - } - - switch (_vm->_map->getCell(14) - 1) { - case 0: - ++_wo[121]; - break; - case 1: - ++_wo[59]; - break; - case 2: - ++_wo[181]; - break; - case 3: - case 12: - ++_wo[101]; - break; - case 4: - case 7: - ++_wo[15]; - break; - case 5: - ++_wo[221]; - break; - case 6: - ++_wo[201]; - break; - case 8: - ++_wo[141]; - break; - case 9: - ++_wo[301]; - break; - case 10: - ++_wo[241]; - break; - case 11: - ++_wo[161]; - break; - case 13: - ++_wo[261]; - break; - case 14: - ++_wo[281]; - break; - default: - break; - } - - switch (_vm->_map->getCell(15) - 1) { - case 1: - ++_wo[63]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[19]; - break; - default: - break; - } - - switch (_vm->_map->getCell(16) - 1) { - case 0: - ++_wo[120]; - break; - case 1: - ++_wo[58]; - break; - case 2: - ++_wo[180]; - break; - case 3: - case 12: - ++_wo[100]; - break; - case 4: - case 7: - ++_wo[14]; - break; - case 5: - ++_wo[220]; - break; - case 6: - ++_wo[200]; - break; - case 8: - ++_wo[140]; - break; - case 9: - ++_wo[300]; - break; - case 10: - ++_wo[240]; - break; - case 11: - ++_wo[160]; - break; - case 13: - ++_wo[260]; - break; - case 14: - ++_wo[280]; - break; - default: - break; - } - - switch (_vm->_map->getCell(17) - 1) { - case 1: - ++_wo[62]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[18]; - break; - default: - break; - } - - switch (_vm->_map->getCell(18) - 1) { - case 0: - ++_wo[119]; - break; - case 1: - ++_wo[57]; - break; - case 2: - ++_wo[179]; - break; - case 3: - case 12: - ++_wo[99]; - break; - case 4: - case 7: - ++_wo[13]; - break; - case 5: - ++_wo[219]; - break; - case 6: - ++_wo[199]; - break; - case 8: - ++_wo[139]; - break; - case 9: - ++_wo[299]; - break; - case 10: - ++_wo[239]; - break; - case 11: - ++_wo[159]; - break; - case 13: - ++_wo[259]; - break; - case 14: - ++_wo[279]; - break; - default: - break; - } - - switch (_vm->_map->getCell(19) - 1) { - case 0: - ++_wo[108]; - break; - case 1: - ++_wo[78]; - break; - case 2: - ++_wo[168]; - case 3: - case 12: - ++_wo[88]; - break; - case 4: - case 7: - ++_wo[34]; - break; - case 5: - ++_wo[208]; - break; - case 6: - ++_wo[188]; - break; - case 8: - ++_wo[128]; - break; - case 9: - ++_wo[288]; - break; - case 10: - ++_wo[228]; - break; - case 11: - ++_wo[148]; - break; - case 13: - ++_wo[248]; - break; - case 14: - ++_wo[268]; - break; - default: - break; - } - - switch (_vm->_map->getCell(20) - 1) { - case 1: - ++_wo[76]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[32]; - break; - default: - break; - } - - switch (_vm->_map->getCell(21) - 1) { - case 0: - ++_wo[109]; - break; - case 1: - ++_wo[44]; - break; - case 2: - ++_wo[169]; - break; - case 3: - case 12: - ++_wo[89]; - break; - case 4: - case 7: - ++_wo[0]; - break; - case 5: - ++_wo[209]; - break; - case 6: - ++_wo[189]; - break; - case 8: - ++_wo[129]; - break; - case 9: - ++_wo[289]; - break; - case 10: - ++_wo[229]; - break; - case 11: - ++_wo[149]; - break; - case 13: - ++_wo[249]; - break; - case 14: - ++_wo[269]; - break; - default: - break; - } - - switch (_vm->_map->getCell(22) - 1) { - case 1: - ++_wo[74]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[30]; - break; - default: - break; - } - - switch (_vm->_map->getCell(23) - 1) { - case 0: - ++_wo[110]; - break; - case 1: - ++_wo[45]; - break; - case 2: - ++_wo[170]; - break; - case 3: - case 12: - ++_wo[90]; - break; - case 4: - case 7: - ++_wo[1]; - break; - case 5: - ++_wo[210]; - break; - case 6: - ++_wo[190]; - break; - case 8: - ++_wo[130]; - break; - case 9: - ++_wo[290]; - break; - case 10: - ++_wo[230]; - break; - case 11: - ++_wo[150]; - break; - case 13: - ++_wo[250]; - break; - case 14: - ++_wo[270]; - break; - default: - break; - } - - switch (_vm->_map->getCell(24) - 1) { - case 1: - ++_wo[52]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[8]; - break; - default: - break; - } - - switch (_vm->_map->getCell(25) - 1) { - case 0: - ++_wo[111]; - break; - case 1: - ++_wo[46]; - break; - case 2: - ++_wo[171]; - break; - case 3: - case 12: - ++_wo[91]; - break; - case 4: - case 7: - ++_wo[2]; - break; - case 5: - ++_wo[211]; - break; - case 6: - ++_wo[191]; - break; - case 8: - ++_wo[131]; - break; - case 9: - ++_wo[291]; - break; - case 10: - ++_wo[231]; - break; - case 11: - ++_wo[151]; - break; - case 13: - ++_wo[251]; - break; - case 14: - ++_wo[271]; - break; - default: - break; - } - - switch (_vm->_map->getCell(26) - 1) { - case 1: - ++_wo[51]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[7]; - break; - default: - break; - } - - switch (_vm->_map->getCell(27) - 1) { - case 0: - ++_wo[116]; - break; - case 1: - ++_wo[50]; - break; - case 2: - ++_wo[176]; - break; - case 3: - case 12: - ++_wo[96]; - break; - case 4: - case 7: - ++_wo[6]; - break; - case 5: - ++_wo[216]; - break; - case 6: - ++_wo[196]; - break; - case 8: - ++_wo[136]; - break; - case 9: - ++_wo[296]; - break; - case 10: - ++_wo[236]; - break; - case 11: - ++_wo[156]; - break; - case 13: - ++_wo[256]; - break; - case 14: - ++_wo[276]; - break; - default: - break; - } - - switch (_vm->_map->getCell(28) - 1) { - case 1: - ++_wo[53]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[9]; - break; - default: - break; - } - - switch (_vm->_map->getCell(29) - 1) { - case 0: - ++_wo[115]; - break; - case 1: - ++_wo[49]; - break; - case 2: - ++_wo[175]; - break; - case 3: - case 12: - ++_wo[95]; - break; - case 4: - case 7: - ++_wo[5]; - break; - case 5: - ++_wo[215]; - break; - case 6: - ++_wo[195]; - break; - case 8: - ++_wo[135]; - break; - case 9: - ++_wo[295]; - break; - case 10: - ++_wo[235]; - break; - case 11: - ++_wo[155]; - break; - case 13: - ++_wo[255]; - break; - case 14: - ++_wo[275]; - break; - default: - break; - } - - switch (_vm->_map->getCell(30) - 1) { - case 1: - ++_wo[54]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[10]; - break; - default: - break; - } - - switch (_vm->_map->getCell(31) - 1) { - case 0: - ++_wo[114]; - break; - case 1: - ++_wo[48]; - break; - case 2: - ++_wo[174]; - break; - case 3: - case 12: - ++_wo[94]; - break; - case 4: - ++_wo[4]; - break; - case 5: - ++_wo[214]; - break; - case 6: - ++_wo[194]; - break; - case 8: - ++_wo[134]; - break; - case 9: - ++_wo[294]; - break; - case 10: - ++_wo[234]; - break; - case 11: - ++_wo[154]; - break; - case 13: - ++_wo[254]; - break; - case 14: - ++_wo[274]; - break; - default: - break; - } - - switch (_vm->_map->getCell(32) - 1) { - case 1: - ++_wo[75]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[31]; - break; - default: - break; - } - - switch (_vm->_map->getCell(33) - 1) { - case 0: - ++_wo[112]; - break; - case 1: - ++_wo[47]; - break; - case 2: - ++_wo[172]; - break; - case 3: - case 12: - ++_wo[92]; - break; - case 4: - case 7: - ++_wo[3]; - break; - case 5: - ++_wo[212]; - break; - case 6: - ++_wo[192]; - break; - case 8: - ++_wo[132]; - break; - case 9: - ++_wo[292]; - break; - case 10: - ++_wo[232]; - break; - case 11: - ++_wo[152]; - break; - case 13: - ++_wo[252]; - break; - case 14: - ++_wo[272]; - break; - default: - break; - } - - switch (_vm->_map->getCell(34) - 1) { - case 1: - ++_wo[77]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[33]; - break; - default: - break; - } - - switch (_vm->_map->getCell(35) - 1) { - case 0: - ++_wo[113]; - break; - case 1: - ++_wo[79]; - break; - case 2: - ++_wo[173]; - break; - case 3: - case 12: - ++_wo[93]; - break; - case 4: - case 7: - ++_wo[35]; - break; - case 5: - ++_wo[213]; - break; - case 6: - ++_wo[193]; - break; - case 8: - ++_wo[133]; - break; - case 9: - ++_wo[293]; - break; - case 10: - ++_wo[233]; - break; - case 11: - ++_wo[153]; - break; - case 13: - ++_wo[253]; - break; - case 14: - ++_wo[273]; - break; - default: - break; - } - - switch (_vm->_map->getCell(36) - 1) { - case 1: - ++_wo[83]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[39]; - break; - default: - break; - } - - switch (_vm->_map->getCell(37) - 1) { - case 1: - ++_wo[82]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[38]; - break; - default: - break; - } - - switch (_vm->_map->getCell(38) - 1) { - case 1: - ++_wo[81]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[37]; - break; - default: - break; - } - - switch (_vm->_map->getCell(34) - 1) { - case 1: - ++_wo[80]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[36]; - break; - default: - break; - } - - switch (_vm->_map->getCell(40) - 1) { - case 1: - ++_wo[84]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[40]; - break; - default: - break; - } - - switch (_vm->_map->getCell(41) - 1) { - case 1: - ++_wo[85]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[41]; - break; - default: - break; - } - - switch (_vm->_map->getCell(42) - 1) { - case 1: - ++_wo[86]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[42]; - break; - default: - break; - } - - switch (_vm->_map->getCell(43) - 1) { - case 1: - ++_wo[87]; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - ++_wo[43]; - break; - default: - break; - } -} - void Interface::drawMiniMap() { Map &map = *_vm->_map; Party &party = *_vm->_party; @@ -2990,7 +1492,8 @@ void Interface::doStepCode() { doFalling(); if ((party._mazePosition.x & 16) || (party._mazePosition.y & 16)) { - map.getNewMaze(); + if (map._isOutdoors) + map.getNewMaze(); } if (damage) { diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 4cd40b9d4f..93c861e0cd 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -72,7 +72,6 @@ private: int _animCounter; bool _isAnimReset; byte _tillMove; - bool _thinWall; int _overallFrame; bool _upDoorText; int _steppingFX; @@ -97,8 +96,6 @@ private: void setMainButtons(); - void setMazeBits(); - void drawMiniMap(); void chargeStep(); diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 5b1d4e995e..c551e5818a 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -373,6 +373,1510 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) { _charsShooting = false; _objNumber = 0; _combatFloatCounter = 0; + _thinWall = false; +} + + +void InterfaceMap::setMazeBits() { + Common::fill(&_wo[0], &_wo[308], 0); + + switch (_vm->_map->getCell(0) - 1) { + case 0: + ++_wo[125]; + break; + case 1: + ++_wo[69]; + break; + case 2: + ++_wo[185]; + break; + case 3: + case 12: + ++_wo[105]; + break; + case 4: + case 7: + ++_wo[25]; + break; + case 5: + ++_wo[225]; + break; + case 6: + ++_wo[205]; + break; + case 8: + ++_wo[145]; + break; + case 9: + ++_wo[305]; + break; + case 10: + ++_wo[245]; + break; + case 11: + ++_wo[165]; + break; + case 13: + ++_wo[265]; + break; + case 14: + ++_wo[285]; + break; + default: + break; + } + + switch (_vm->_map->getCell(1) - 1) { + case 1: + ++_wo[72]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[28]; + break; + default: + break; + } + + switch (_vm->_map->getCell(2) - 1) { + case 0: + ++_wo[127]; + break; + case 1: + ++_wo[71]; + break; + case 2: + ++_wo[187]; + break; + case 3: + case 12: + ++_wo[107]; + break; + case 4: + case 7: + ++_wo[27]; + break; + case 5: + ++_wo[227]; + break; + case 6: + ++_wo[207]; + break; + case 8: + ++_wo[147]; + break; + case 9: + ++_wo[307]; + break; + case 10: + ++_wo[247]; + break; + case 11: + ++_wo[167]; + break; + case 13: + ++_wo[267]; + break; + case 14: + ++_wo[287]; + break; + default: + break; + } + + _vm->_party->handleLight(); + + switch (_vm->_map->getCell(3) - 1) { + case 1: + ++_wo[73]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[29]; + break; + default: + break; + } + + switch (_vm->_map->getCell(4) - 1) { + case 0: + ++_wo[126]; + break; + case 1: + ++_wo[70]; + break; + case 2: + ++_wo[186]; + break; + case 3: + case 12: + ++_wo[106]; + break; + case 4: + case 7: + ++_wo[26]; + break; + case 5: + ++_wo[226]; + break; + case 6: + ++_wo[206]; + case 8: + ++_wo[146]; + break; + case 9: + ++_wo[306]; + break; + case 10: + ++_wo[246]; + break; + break; + case 11: + ++_wo[166]; + break; + case 13: + ++_wo[266]; + break; + case 14: + ++_wo[286]; + break; + default: + break; + } + + switch (_vm->_map->getCell(5) - 1) { + case 0: + ++_wo[122]; + break; + case 1: + ++_wo[64]; + break; + case 2: + ++_wo[182]; + break; + case 3: + case 12: + ++_wo[102]; + break; + case 4: + case 7: + ++_wo[20]; + break; + case 5: + ++_wo[222]; + break; + case 6: + ++_wo[202]; + break; + case 8: + ++_wo[142]; + break; + case 9: + ++_wo[302]; + break; + case 10: + ++_wo[242]; + break; + case 11: + ++_wo[162]; + break; + case 13: + ++_wo[262]; + break; + case 14: + ++_wo[282]; + break; + default: + break; + } + + switch (_vm->_map->getCell(6) - 1) { + case 1: + ++_wo[67]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[23]; + break; + default: + break; + } + + switch (_vm->_map->getCell(7) - 1) { + case 0: + ++_wo[124]; + break; + case 1: + ++_wo[66]; + break; + case 2: + ++_wo[184]; + break; + case 3: + case 12: + ++_wo[104]; + break; + case 4: + case 7: + ++_wo[22]; + break; + case 5: + ++_wo[224]; + break; + case 6: + ++_wo[204]; + break; + case 8: + ++_wo[144]; + break; + case 9: + ++_wo[304]; + break; + case 10: + ++_wo[244]; + break; + case 11: + ++_wo[164]; + break; + case 13: + ++_wo[264]; + break; + case 14: + ++_wo[284]; + break; + default: + break; + } + + _thinWall = (_vm->_map->_currentWall._data != INVALID_CELL) && _wo[27]; + + switch (_vm->_map->getCell(8) - 1) { + case 1: + ++_wo[68]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[24]; + break; + default: + break; + } + + switch (_vm->_map->getCell(9) - 1) { + case 0: + ++_wo[123]; + break; + case 1: + ++_wo[65]; + break; + case 2: + ++_wo[183]; + break; + case 3: + case 12: + ++_wo[103]; + break; + case 4: + case 7: + ++_wo[21]; + break; + case 5: + ++_wo[223]; + break; + case 6: + ++_wo[203]; + break; + case 8: + ++_wo[143]; + break; + case 9: + ++_wo[3033]; + break; + case 10: + ++_wo[243]; + break; + case 11: + ++_wo[163]; + break; + case 13: + ++_wo[263]; + break; + case 14: + ++_wo[283]; + break; + default: + break; + } + + switch (_vm->_map->getCell(10) - 1) { + case 0: + ++_wo[117]; + break; + case 1: + ++_wo[55]; + break; + case 2: + ++_wo[177]; + break; + case 3: + case 12: + ++_wo[97]; + break; + case 4: + case 7: + ++_wo[11]; + break; + case 5: + ++_wo[217]; + break; + case 6: + ++_wo[197]; + break; + case 8: + ++_wo[137]; + break; + case 9: + ++_wo[297]; + break; + case 10: + ++_wo[237]; + case 11: + ++_wo[157]; + break; + case 13: + ++_wo[257]; + break; + case 14: + ++_wo[277]; + break; + default: + break; + } + + switch (_vm->_map->getCell(11) - 1) { + case 1: + ++_wo[60]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[16]; + break; + default: + break; + } + + switch (_vm->_map->getCell(12) - 1) { + case 0: + ++_wo[118]; + break; + case 1: + ++_wo[56]; + break; + case 2: + ++_wo[178]; + break; + case 3: + case 12: + ++_wo[98]; + break; + case 4: + case 7: + ++_wo[12]; + break; + case 5: + ++_wo[218]; + break; + case 6: + ++_wo[198]; + break; + case 8: + ++_wo[138]; + break; + case 9: + ++_wo[298]; + break; + case 10: + ++_wo[238]; + break; + case 11: + ++_wo[158]; + break; + case 13: + ++_wo[258]; + break; + case 14: + ++_wo[278]; + break; + default: + break; + } + + switch (_vm->_map->getCell(13) - 1) { + case 1: + ++_wo[61]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[17]; + break; + default: + break; + } + + switch (_vm->_map->getCell(14) - 1) { + case 0: + ++_wo[121]; + break; + case 1: + ++_wo[59]; + break; + case 2: + ++_wo[181]; + break; + case 3: + case 12: + ++_wo[101]; + break; + case 4: + case 7: + ++_wo[15]; + break; + case 5: + ++_wo[221]; + break; + case 6: + ++_wo[201]; + break; + case 8: + ++_wo[141]; + break; + case 9: + ++_wo[301]; + break; + case 10: + ++_wo[241]; + break; + case 11: + ++_wo[161]; + break; + case 13: + ++_wo[261]; + break; + case 14: + ++_wo[281]; + break; + default: + break; + } + + switch (_vm->_map->getCell(15) - 1) { + case 1: + ++_wo[63]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[19]; + break; + default: + break; + } + + switch (_vm->_map->getCell(16) - 1) { + case 0: + ++_wo[120]; + break; + case 1: + ++_wo[58]; + break; + case 2: + ++_wo[180]; + break; + case 3: + case 12: + ++_wo[100]; + break; + case 4: + case 7: + ++_wo[14]; + break; + case 5: + ++_wo[220]; + break; + case 6: + ++_wo[200]; + break; + case 8: + ++_wo[140]; + break; + case 9: + ++_wo[300]; + break; + case 10: + ++_wo[240]; + break; + case 11: + ++_wo[160]; + break; + case 13: + ++_wo[260]; + break; + case 14: + ++_wo[280]; + break; + default: + break; + } + + switch (_vm->_map->getCell(17) - 1) { + case 1: + ++_wo[62]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[18]; + break; + default: + break; + } + + switch (_vm->_map->getCell(18) - 1) { + case 0: + ++_wo[119]; + break; + case 1: + ++_wo[57]; + break; + case 2: + ++_wo[179]; + break; + case 3: + case 12: + ++_wo[99]; + break; + case 4: + case 7: + ++_wo[13]; + break; + case 5: + ++_wo[219]; + break; + case 6: + ++_wo[199]; + break; + case 8: + ++_wo[139]; + break; + case 9: + ++_wo[299]; + break; + case 10: + ++_wo[239]; + break; + case 11: + ++_wo[159]; + break; + case 13: + ++_wo[259]; + break; + case 14: + ++_wo[279]; + break; + default: + break; + } + + switch (_vm->_map->getCell(19) - 1) { + case 0: + ++_wo[108]; + break; + case 1: + ++_wo[78]; + break; + case 2: + ++_wo[168]; + case 3: + case 12: + ++_wo[88]; + break; + case 4: + case 7: + ++_wo[34]; + break; + case 5: + ++_wo[208]; + break; + case 6: + ++_wo[188]; + break; + case 8: + ++_wo[128]; + break; + case 9: + ++_wo[288]; + break; + case 10: + ++_wo[228]; + break; + case 11: + ++_wo[148]; + break; + case 13: + ++_wo[248]; + break; + case 14: + ++_wo[268]; + break; + default: + break; + } + + switch (_vm->_map->getCell(20) - 1) { + case 1: + ++_wo[76]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[32]; + break; + default: + break; + } + + switch (_vm->_map->getCell(21) - 1) { + case 0: + ++_wo[109]; + break; + case 1: + ++_wo[44]; + break; + case 2: + ++_wo[169]; + break; + case 3: + case 12: + ++_wo[89]; + break; + case 4: + case 7: + ++_wo[0]; + break; + case 5: + ++_wo[209]; + break; + case 6: + ++_wo[189]; + break; + case 8: + ++_wo[129]; + break; + case 9: + ++_wo[289]; + break; + case 10: + ++_wo[229]; + break; + case 11: + ++_wo[149]; + break; + case 13: + ++_wo[249]; + break; + case 14: + ++_wo[269]; + break; + default: + break; + } + + switch (_vm->_map->getCell(22) - 1) { + case 1: + ++_wo[74]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[30]; + break; + default: + break; + } + + switch (_vm->_map->getCell(23) - 1) { + case 0: + ++_wo[110]; + break; + case 1: + ++_wo[45]; + break; + case 2: + ++_wo[170]; + break; + case 3: + case 12: + ++_wo[90]; + break; + case 4: + case 7: + ++_wo[1]; + break; + case 5: + ++_wo[210]; + break; + case 6: + ++_wo[190]; + break; + case 8: + ++_wo[130]; + break; + case 9: + ++_wo[290]; + break; + case 10: + ++_wo[230]; + break; + case 11: + ++_wo[150]; + break; + case 13: + ++_wo[250]; + break; + case 14: + ++_wo[270]; + break; + default: + break; + } + + switch (_vm->_map->getCell(24) - 1) { + case 1: + ++_wo[52]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[8]; + break; + default: + break; + } + + switch (_vm->_map->getCell(25) - 1) { + case 0: + ++_wo[111]; + break; + case 1: + ++_wo[46]; + break; + case 2: + ++_wo[171]; + break; + case 3: + case 12: + ++_wo[91]; + break; + case 4: + case 7: + ++_wo[2]; + break; + case 5: + ++_wo[211]; + break; + case 6: + ++_wo[191]; + break; + case 8: + ++_wo[131]; + break; + case 9: + ++_wo[291]; + break; + case 10: + ++_wo[231]; + break; + case 11: + ++_wo[151]; + break; + case 13: + ++_wo[251]; + break; + case 14: + ++_wo[271]; + break; + default: + break; + } + + switch (_vm->_map->getCell(26) - 1) { + case 1: + ++_wo[51]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[7]; + break; + default: + break; + } + + switch (_vm->_map->getCell(27) - 1) { + case 0: + ++_wo[116]; + break; + case 1: + ++_wo[50]; + break; + case 2: + ++_wo[176]; + break; + case 3: + case 12: + ++_wo[96]; + break; + case 4: + case 7: + ++_wo[6]; + break; + case 5: + ++_wo[216]; + break; + case 6: + ++_wo[196]; + break; + case 8: + ++_wo[136]; + break; + case 9: + ++_wo[296]; + break; + case 10: + ++_wo[236]; + break; + case 11: + ++_wo[156]; + break; + case 13: + ++_wo[256]; + break; + case 14: + ++_wo[276]; + break; + default: + break; + } + + switch (_vm->_map->getCell(28) - 1) { + case 1: + ++_wo[53]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[9]; + break; + default: + break; + } + + switch (_vm->_map->getCell(29) - 1) { + case 0: + ++_wo[115]; + break; + case 1: + ++_wo[49]; + break; + case 2: + ++_wo[175]; + break; + case 3: + case 12: + ++_wo[95]; + break; + case 4: + case 7: + ++_wo[5]; + break; + case 5: + ++_wo[215]; + break; + case 6: + ++_wo[195]; + break; + case 8: + ++_wo[135]; + break; + case 9: + ++_wo[295]; + break; + case 10: + ++_wo[235]; + break; + case 11: + ++_wo[155]; + break; + case 13: + ++_wo[255]; + break; + case 14: + ++_wo[275]; + break; + default: + break; + } + + switch (_vm->_map->getCell(30) - 1) { + case 1: + ++_wo[54]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[10]; + break; + default: + break; + } + + switch (_vm->_map->getCell(31) - 1) { + case 0: + ++_wo[114]; + break; + case 1: + ++_wo[48]; + break; + case 2: + ++_wo[174]; + break; + case 3: + case 12: + ++_wo[94]; + break; + case 4: + case 7: + ++_wo[4]; + break; + case 5: + ++_wo[214]; + break; + case 6: + ++_wo[194]; + break; + case 8: + ++_wo[134]; + break; + case 9: + ++_wo[294]; + break; + case 10: + ++_wo[234]; + break; + case 11: + ++_wo[154]; + break; + case 13: + ++_wo[254]; + break; + case 14: + ++_wo[274]; + break; + default: + break; + } + + switch (_vm->_map->getCell(32) - 1) { + case 1: + ++_wo[75]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[31]; + break; + default: + break; + } + + switch (_vm->_map->getCell(33) - 1) { + case 0: + ++_wo[112]; + break; + case 1: + ++_wo[47]; + break; + case 2: + ++_wo[172]; + break; + case 3: + case 12: + ++_wo[92]; + break; + case 4: + case 7: + ++_wo[3]; + break; + case 5: + ++_wo[212]; + break; + case 6: + ++_wo[192]; + break; + case 8: + ++_wo[132]; + break; + case 9: + ++_wo[292]; + break; + case 10: + ++_wo[232]; + break; + case 11: + ++_wo[152]; + break; + case 13: + ++_wo[252]; + break; + case 14: + ++_wo[272]; + break; + default: + break; + } + + switch (_vm->_map->getCell(34) - 1) { + case 1: + ++_wo[77]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[33]; + break; + default: + break; + } + + switch (_vm->_map->getCell(35) - 1) { + case 0: + ++_wo[113]; + break; + case 1: + ++_wo[79]; + break; + case 2: + ++_wo[173]; + break; + case 3: + case 12: + ++_wo[93]; + break; + case 4: + case 7: + ++_wo[35]; + break; + case 5: + ++_wo[213]; + break; + case 6: + ++_wo[193]; + break; + case 8: + ++_wo[133]; + break; + case 9: + ++_wo[293]; + break; + case 10: + ++_wo[233]; + break; + case 11: + ++_wo[153]; + break; + case 13: + ++_wo[253]; + break; + case 14: + ++_wo[273]; + break; + default: + break; + } + + switch (_vm->_map->getCell(36) - 1) { + case 1: + ++_wo[83]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[39]; + break; + default: + break; + } + + switch (_vm->_map->getCell(37) - 1) { + case 1: + ++_wo[82]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[38]; + break; + default: + break; + } + + switch (_vm->_map->getCell(38) - 1) { + case 1: + ++_wo[81]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[37]; + break; + default: + break; + } + + switch (_vm->_map->getCell(34) - 1) { + case 1: + ++_wo[77]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[33]; + break; + default: + break; + } + + switch (_vm->_map->getCell(40) - 1) { + case 1: + ++_wo[84]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[40]; + break; + default: + break; + } + + switch (_vm->_map->getCell(41) - 1) { + case 1: + ++_wo[85]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[41]; + break; + default: + break; + } + + switch (_vm->_map->getCell(42) - 1) { + case 1: + ++_wo[86]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[42]; + break; + default: + break; + } + + switch (_vm->_map->getCell(43) - 1) { + case 1: + ++_wo[87]; + break; + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + ++_wo[43]; + break; + default: + break; + } } void InterfaceMap::setIndoorsMonsters() { diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index be17ef0024..189598bb5c 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -100,6 +100,9 @@ protected: bool _isShooting; bool _charsShooting; int _objNumber; + bool _thinWall; + + void setMazeBits(); public: OutdoorDrawList _outdoorList; IndoorDrawList _indoorList; -- cgit v1.2.3 From adce5f9c2030813936268c0b7e58a33b6cfce003 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 20 Jan 2015 21:37:57 -0500 Subject: XEEN: Convert map _skySprites into a 2 element array --- engines/xeen/interface_map.cpp | 8 +++----- engines/xeen/map.cpp | 10 +++++----- engines/xeen/map.h | 5 ++--- 3 files changed, 10 insertions(+), 13 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index c551e5818a..2c1b973fd6 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -3418,10 +3418,8 @@ void InterfaceMap::drawIndoors() { map.cellFlagLookup(_vm->_party->_mazePosition); - // WORKAROUND: Original did an array lookup on _skySprites. - // Was this a feature for multiple skys that was abandoned? - assert(!map._currentSky); - _indoorList[0]._sprites = &map._skySprites; + assert(map._currentSky < 2); + _indoorList[0]._sprites = &map._skySprites[map._currentSky]; _indoorList[0]._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0; if (_vm->_openDoor) { @@ -3433,7 +3431,7 @@ void InterfaceMap::drawIndoors() { ); map.cellFlagLookup(pt); - _indoorList._sky2._sprites = &map._skySprites; + _indoorList._sky2._sprites = &map._skySprites[0]; } else { _indoorList._sky2._sprites = _indoorList[0]._sprites; } diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 6b577ebd45..e541d374d6 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -868,7 +868,7 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { _currentCantRest = false; _currentIsDrain = false; _currentIsEvent = false; - _currentSky = false; + _currentSky = 0; _currentMonsterFlags = 0; } @@ -1082,7 +1082,7 @@ void Map::load(int mapId) { _groundSprites.load("water.out"); _tileSprites.load("outdoor.til"); - outdoorList._skySprite._sprites = &_skySprites; + outdoorList._skySprite._sprites = &_skySprites[0]; outdoorList._groundSprite._sprites = &_groundSprites; for (int i = 0; i < TOTAL_SURFACES; ++i) { @@ -1100,7 +1100,7 @@ void Map::load(int mapId) { } else { warning("TODO"); // Sound loading - _mazeSkySprites.load(Common::String::format("%s.sky", + _skySprites[1].load(Common::String::format("%s.sky", TERRAIN_TYPES[_mazeData[0]._wallKind])); _groundSprites.load(Common::String::format("%s.gnd", TERRAIN_TYPES[_mazeData[0]._wallKind])); @@ -1354,7 +1354,7 @@ void Map::cellFlagLookup(const Common::Point &pt) { _currentCantRest = cell._flags & FLAG_WATER; _currentIsDrain = cell._flags & OUTFLAG_DRAIN; _currentIsEvent = cell._flags & FLAG_AUTOEXECUTE_EVENT; - _currentSky = cell._flags & OUTFLAG_OBJECT_EXISTS; + _currentSky = (cell._flags & OUTFLAG_OBJECT_EXISTS) ? 1 : 0; _currentMonsterFlags = cell._flags & 7; } @@ -1495,7 +1495,7 @@ void Map::loadSky() { Party &party = *_vm->_party; party._isNight = party._minutes < (5 * 60) || party._minutes >= (21 * 60); - _skySprites.load(((party._mazeId >= 89 && party._mazeId <= 112) || + _skySprites[0].load(((party._mazeId >= 89 && party._mazeId <= 112) || party._mazeId == 128 || party._mazeId == 129) || !party._isNight ? "sky.sky" : "night.sky"); } diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 32418257f4..d8444eb0ff 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -354,8 +354,7 @@ public: MazeEvents _events; HeadData _headData; AnimationInfo _animationInfo; - SpriteResource _skySprites; - SpriteResource _mazeSkySprites; + SpriteResource _skySprites[2]; SpriteResource _groundSprites; SpriteResource _tileSprites; SpriteResource _surfaceSprites[TOTAL_SURFACES]; @@ -364,7 +363,7 @@ public: bool _currentCantRest; bool _currentIsDrain; bool _currentIsEvent; - bool _currentSky; + int _currentSky; int _currentMonsterFlags; MazeWallLayers _currentWall; int _currentTile; -- cgit v1.2.3 From 69ca508e8fd16e79bfa5a0f66ced3ccf9fb2dbf8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 20 Jan 2015 22:13:26 -0500 Subject: XEEN: Fix settig stepped on tiles --- engines/xeen/interface_map.cpp | 6 +++--- engines/xeen/map.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 2c1b973fd6..4ff64b38eb 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -1758,9 +1758,9 @@ void InterfaceMap::setMazeBits() { break; } - switch (_vm->_map->getCell(34) - 1) { + switch (_vm->_map->getCell(39) - 1) { case 1: - ++_wo[77]; + ++_wo[80]; break; case 0: case 2: @@ -1776,7 +1776,7 @@ void InterfaceMap::setMazeBits() { case 12: case 13: case 14: - ++_wo[33]; + ++_wo[36]; break; default: break; diff --git a/engines/xeen/map.h b/engines/xeen/map.h index d8444eb0ff..8735973738 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -384,9 +384,9 @@ public: int getCell(int idx); - MazeData mazeData() { return _mazeData[0]; } + MazeData &mazeData() { return _mazeData[0]; } - MazeData mazeDataCurrent() { return _mazeData[_mazeDataIndex]; } + MazeData &mazeDataCurrent() { return _mazeData[_mazeDataIndex]; } void loadSky(); -- cgit v1.2.3 From 932222de7dd32ff0a0b643a2e9d756160bff27bf Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 21 Jan 2015 20:42:44 -0500 Subject: XEEN: Skeleton beginnings of script handling --- engines/xeen/files.cpp | 11 ++++ engines/xeen/files.h | 2 + engines/xeen/interface.cpp | 4 +- engines/xeen/interface.h | 3 +- engines/xeen/map.cpp | 5 +- engines/xeen/scripts.cpp | 161 +++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/scripts.h | 78 +++++++++++++++++++++- 7 files changed, 257 insertions(+), 7 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index f8e7a3fc0c..0c3402f00d 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -232,4 +232,15 @@ void File::openFile(const Common::String &filename, Common::Archive &archive) { error("Could not open file - %s", filename.c_str()); } +Common::String File::readString() { + Common::String result; + char c; + + while (pos() < size() && (c = (char)readByte()) != '\0') + result += c; + + return result; +} + + } // End of namespace Xeen diff --git a/engines/xeen/files.h b/engines/xeen/files.h index f350e34166..f0c92d1050 100644 --- a/engines/xeen/files.h +++ b/engines/xeen/files.h @@ -75,6 +75,8 @@ public: void openFile(const Common::String &filename); void openFile(const Common::String &filename, Common::Archive &archive); + + Common::String readString(); }; class XeenSerializer : public Common::Serializer { diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index d2fea36872..e31b9e240a 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -43,7 +43,6 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm( _hiliteChar = -1; _intrIndex1 = 0; _flag1 = false; - _animCounter = 0; _isAnimReset = false; _tillMove = 0; _overallFrame = 0; @@ -542,6 +541,7 @@ void Interface::draw3d(bool updateFlag) { Map &map = *_vm->_map; Party &party = *_vm->_party; Screen &screen = *_vm->_screen; + Scripts &scripts = *_vm->_scripts; if (screen._windows[11]._enabled) return; @@ -570,7 +570,7 @@ void Interface::draw3d(bool updateFlag) { mazeObject._frame = animEntry._frame1._frames[directionIndex]; } else { ++mazeObject._frame; - if ((int)idx == objNum && _animCounter > 0 && ( + if ((int)idx == objNum && scripts._animCounter > 0 && ( objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) || objObject._spriteId == 58 || objObject._spriteId == 73)) { if (mazeObject._frame > 4 || mazeObject._spriteId == 58) diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 93c861e0cd..37ac7be5be 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -66,10 +66,8 @@ private: int _heroismUIFrame; int _flipUIFrame; bool _buttonsLoaded; - Common::String _interfaceText; int _hiliteChar; bool _flag1; - int _animCounter; bool _isAnimReset; byte _tillMove; int _overallFrame; @@ -107,6 +105,7 @@ private: bool checkMoveDirection(int key); public: int _intrIndex1; + Common::String _interfaceText; public: Interface(XeenEngine *vm); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index e541d374d6..d2f4c5e18d 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1284,8 +1284,9 @@ void Map::loadEvents(int mapId) { filename = Common::String::format("aaze%c%03d.txt", (mapId >= 100) ? 'x' : '0', mapId); File fText(filename); - _events._text.resize(fText.size()); - fText.read(&_events._text[0], fText.size()); + _events._text.clear(); + while (fText.pos() < fText.size()) + _events._text.push_back(fText.readString()); fText.close(); } diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 55388ec343..50584a2551 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -22,6 +22,7 @@ #include "xeen/scripts.h" #include "xeen/party.h" +#include "xeen/xeen.h" namespace Xeen { @@ -65,9 +66,76 @@ void MazeEvents::synchronize(XeenSerializer &s) { /*------------------------------------------------------------------------*/ Scripts::Scripts(XeenEngine *vm) : _vm(vm) { + Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0); + _whoWill = 0; + _itemType = 0; + _treasureItems = 0; + _treasureGold = 0; + _treasureGems = 0; + + _v2 = 0; + _nEdamageType = 0; + _animCounter = 0; + _eventSkipped = false; } void Scripts::checkEvents() { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + + int var18 = 0; + _itemType = 0; + int var4F = 0; + bool var50 = false; + _whoWill = 0; + Mode oldMode = _vm->_mode; + Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0); + int items = _treasureItems; + + if (_treasureGold & _treasureItems) { + // TODO + } else { + // TODO + } + + do { + int var4 = 0; + int varA = 0; + _animCounter = 0; + int var4E = 0; + const Common::Point pt = party._mazePosition; + int varC = 1; + _v2 = 1; + _nEdamageType = 0; + int var40 = -1; + + // Break out of the events if there's an attacking monster + if (combat._attackMonsters[0] != -1) { + _eventSkipped = true; + break; + } + + _eventSkipped = false; + + for (uint eventIndex = 0; eventIndex < map._events.size(); ++eventIndex) { + MazeEvent &event = map._events[eventIndex]; + + if (event._position == pt && party._mazeDirection != (pt.x | pt.y)) { + if (event._direction == party._mazeDirection || event._direction == DIR_ALL) { + _vm->_mode = MODE_9; + intf._interfaceText = event._parameters.size() == 0 ? "" : + map._events._text[event._parameters[0]]; + doOpcode(event._opcode, event._parameters); + + } else { + var50 = true; + } + } + } + } while (0); + // TODO } @@ -79,4 +147,97 @@ void Scripts::openGrate(int v1, int v2) { // TODO } +typedef void(Scripts::*ScriptMethodPtr)(Common::Array<byte> &); + +void Scripts::doOpcode(Opcode opcode, Common::Array<byte> ¶ms) { + static const ScriptMethodPtr COMMAND_LIST[] = { + &Scripts::cmdNone, &Scripts::cmdDisplay0x01, &Scripts::cmdDoorTextSml, + &Scripts::cmdDoorTextLrg, &Scripts::cmdSignText, + &Scripts::cmdNPC, &Scripts::cmdPlayFX, &Scripts::cmdTeleportAndExit, + &Scripts::cmdIf1, &Scripts::cmdIf2, &Scripts::cmdIf3, + &Scripts::cmdMoveObj, &Scripts::cmdTakeOrGive, &Scripts::cmdNoAction, + &Scripts::cmdRemove, &Scripts::cmdSetChar, &Scripts::cmdSpawn, + &Scripts::cmdDoTownEvent, &Scripts::cmdExit, &Scripts::cmdAfterMap, + &Scripts::cmdGiveExtended, &Scripts::cmdConfirmWord, &Scripts::cmdDamage, + &Scripts::cmdJumpRnd, &Scripts::cmdAfterEvent, &Scripts::cmdCallEvent, + &Scripts::cmdReturn, &Scripts::cmdSetVar, &Scripts::cmdTakeOrGive2, + &Scripts::cmdTakeOrGive3, &Scripts::cmdCutsceneEndClouds, + &Scripts::cmdTeleportAndContinue, &Scripts::cmdWhoWill, + &Scripts::cmdRndDamage, &Scripts::cmdMoveWallObj, &Scripts::cmdAlterCellFlag, + &Scripts::cmdAlterHed, &Scripts::cmdDisplayStat, &Scripts::cmdTakeOrGive4, + &Scripts::cmdSeatTextSml, &Scripts::cmdPlayEventVoc, &Scripts::cmdDisplayBottom, + &Scripts::cmdIfMapFlag, &Scripts::cmdSelRndChar, &Scripts::cmdGiveEnchanted, + &Scripts::cmdItemType, &Scripts::cmdMakeNothingHere, &Scripts::cmdNoAction2, + &Scripts::cmdChooseNumeric, &Scripts::cmdDisplayBottomTwoLines, + &Scripts::cmdDisplayLarge, &Scripts::cmdExchObj, &Scripts::cmdFallToMap, + &Scripts::cmdDisplayMain, &Scripts::cmdGoto, &Scripts::cmdConfirmWord2, + &Scripts::cmdGotoRandom, &Scripts::cmdCutsceneEndDarkside, + &Scripts::cmdCutsceneEdWorld, &Scripts::cmdFlipWorld, &Scripts::cmdPlayCD + }; + + (this->*COMMAND_LIST[opcode])(params); +} + +void Scripts::cmdNone(Common::Array<byte> ¶ms) {} +void Scripts::cmdDisplay0x01(Common::Array<byte> ¶ms) {} +void Scripts::cmdDoorTextSml(Common::Array<byte> ¶ms) {} +void Scripts::cmdDoorTextLrg(Common::Array<byte> ¶ms) {} +void Scripts::cmdSignText(Common::Array<byte> ¶ms) {} +void Scripts::cmdNPC(Common::Array<byte> ¶ms) {} +void Scripts::cmdPlayFX(Common::Array<byte> ¶ms) {} +void Scripts::cmdTeleportAndExit(Common::Array<byte> ¶ms) {} +void Scripts::cmdIf1(Common::Array<byte> ¶ms) {} +void Scripts::cmdIf2(Common::Array<byte> ¶ms) {} +void Scripts::cmdIf3(Common::Array<byte> ¶ms) {} +void Scripts::cmdMoveObj(Common::Array<byte> ¶ms) {} +void Scripts::cmdTakeOrGive(Common::Array<byte> ¶ms) {} +void Scripts::cmdNoAction(Common::Array<byte> ¶ms) {} +void Scripts::cmdRemove(Common::Array<byte> ¶ms) {} +void Scripts::cmdSetChar(Common::Array<byte> ¶ms) {} +void Scripts::cmdSpawn(Common::Array<byte> ¶ms) {} +void Scripts::cmdDoTownEvent(Common::Array<byte> ¶ms) {} +void Scripts::cmdExit(Common::Array<byte> ¶ms) {} +void Scripts::cmdAfterMap(Common::Array<byte> ¶ms) {} +void Scripts::cmdGiveExtended(Common::Array<byte> ¶ms) {} +void Scripts::cmdConfirmWord(Common::Array<byte> ¶ms) {} +void Scripts::cmdDamage(Common::Array<byte> ¶ms) {} +void Scripts::cmdJumpRnd(Common::Array<byte> ¶ms) {} +void Scripts::cmdAfterEvent(Common::Array<byte> ¶ms) {} +void Scripts::cmdCallEvent(Common::Array<byte> ¶ms) {} +void Scripts::cmdReturn(Common::Array<byte> ¶ms) {} +void Scripts::cmdSetVar(Common::Array<byte> ¶ms) {} +void Scripts::cmdTakeOrGive2(Common::Array<byte> ¶ms) {} +void Scripts::cmdTakeOrGive3(Common::Array<byte> ¶ms) {} +void Scripts::cmdCutsceneEndClouds(Common::Array<byte> ¶ms) {} +void Scripts::cmdTeleportAndContinue(Common::Array<byte> ¶ms) {} +void Scripts::cmdWhoWill(Common::Array<byte> ¶ms) {} +void Scripts::cmdRndDamage(Common::Array<byte> ¶ms) {} +void Scripts::cmdMoveWallObj(Common::Array<byte> ¶ms) {} +void Scripts::cmdAlterCellFlag(Common::Array<byte> ¶ms) {} +void Scripts::cmdAlterHed(Common::Array<byte> ¶ms) {} +void Scripts::cmdDisplayStat(Common::Array<byte> ¶ms) {} +void Scripts::cmdTakeOrGive4(Common::Array<byte> ¶ms) {} +void Scripts::cmdSeatTextSml(Common::Array<byte> ¶ms) {} +void Scripts::cmdPlayEventVoc(Common::Array<byte> ¶ms) {} +void Scripts::cmdDisplayBottom(Common::Array<byte> ¶ms) {} +void Scripts::cmdIfMapFlag(Common::Array<byte> ¶ms) {} +void Scripts::cmdSelRndChar(Common::Array<byte> ¶ms) {} +void Scripts::cmdGiveEnchanted(Common::Array<byte> ¶ms) {} +void Scripts::cmdItemType(Common::Array<byte> ¶ms) {} +void Scripts::cmdMakeNothingHere(Common::Array<byte> ¶ms) {} +void Scripts::cmdNoAction2(Common::Array<byte> ¶ms) {} +void Scripts::cmdChooseNumeric(Common::Array<byte> ¶ms) {} +void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> ¶ms) {} +void Scripts::cmdDisplayLarge(Common::Array<byte> ¶ms) {} +void Scripts::cmdExchObj(Common::Array<byte> ¶ms) {} +void Scripts::cmdFallToMap(Common::Array<byte> ¶ms) {} +void Scripts::cmdDisplayMain(Common::Array<byte> ¶ms) {} +void Scripts::cmdGoto(Common::Array<byte> ¶ms) {} +void Scripts::cmdConfirmWord2(Common::Array<byte> ¶ms) {} +void Scripts::cmdGotoRandom(Common::Array<byte> ¶ms) {} +void Scripts::cmdCutsceneEndDarkside(Common::Array<byte> ¶ms) {} +void Scripts::cmdCutsceneEdWorld(Common::Array<byte> ¶ms) {} +void Scripts::cmdFlipWorld(Common::Array<byte> ¶ms) {} +void Scripts::cmdPlayCD(Common::Array<byte> ¶ms) {} + } // End of namespace Xeen diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 9974892221..2fbcf78b38 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/system.h" #include "common/serializer.h" +#include "common/str-array.h" #include "xeen/files.h" namespace Xeen { @@ -111,7 +112,7 @@ public: class MazeEvents : public Common::Array<MazeEvent> { public: - Common::Array<byte> _text; + Common::StringArray _text; public: void synchronize(XeenSerializer &s); }; @@ -119,6 +120,81 @@ public: class Scripts { private: XeenEngine *_vm; + int _charFX[6]; + int _whoWill; + int _itemType; + int _treasureItems; + int _treasureGold; + int _treasureGems; + + int _v2; + int _nEdamageType; + + void doOpcode(Opcode opcode, Common::Array<byte> ¶ms); + void cmdNone(Common::Array<byte> ¶ms); + void cmdDisplay0x01(Common::Array<byte> ¶ms); + void cmdDoorTextSml(Common::Array<byte> ¶ms); + void cmdDoorTextLrg(Common::Array<byte> ¶ms); + void cmdSignText(Common::Array<byte> ¶ms); + void cmdNPC(Common::Array<byte> ¶ms); + void cmdPlayFX(Common::Array<byte> ¶ms); + void cmdTeleportAndExit(Common::Array<byte> ¶ms); + void cmdIf1(Common::Array<byte> ¶ms); + void cmdIf2(Common::Array<byte> ¶ms); + void cmdIf3(Common::Array<byte> ¶ms); + void cmdMoveObj(Common::Array<byte> ¶ms); + void cmdTakeOrGive(Common::Array<byte> ¶ms); + void cmdNoAction(Common::Array<byte> ¶ms); + void cmdRemove(Common::Array<byte> ¶ms); + void cmdSetChar(Common::Array<byte> ¶ms); + void cmdSpawn(Common::Array<byte> ¶ms); + void cmdDoTownEvent(Common::Array<byte> ¶ms); + void cmdExit(Common::Array<byte> ¶ms); + void cmdAfterMap(Common::Array<byte> ¶ms); + void cmdGiveExtended(Common::Array<byte> ¶ms); + void cmdConfirmWord(Common::Array<byte> ¶ms); + void cmdDamage(Common::Array<byte> ¶ms); + void cmdJumpRnd(Common::Array<byte> ¶ms); + void cmdAfterEvent(Common::Array<byte> ¶ms); + void cmdCallEvent(Common::Array<byte> ¶ms); + void cmdReturn(Common::Array<byte> ¶ms); + void cmdSetVar(Common::Array<byte> ¶ms); + void cmdTakeOrGive2(Common::Array<byte> ¶ms); + void cmdTakeOrGive3(Common::Array<byte> ¶ms); + void cmdCutsceneEndClouds(Common::Array<byte> ¶ms); + void cmdTeleportAndContinue(Common::Array<byte> ¶ms); + void cmdWhoWill(Common::Array<byte> ¶ms); + void cmdRndDamage(Common::Array<byte> ¶ms); + void cmdMoveWallObj(Common::Array<byte> ¶ms); + void cmdAlterCellFlag(Common::Array<byte> ¶ms); + void cmdAlterHed(Common::Array<byte> ¶ms); + void cmdDisplayStat(Common::Array<byte> ¶ms); + void cmdTakeOrGive4(Common::Array<byte> ¶ms); + void cmdSeatTextSml(Common::Array<byte> ¶ms); + void cmdPlayEventVoc(Common::Array<byte> ¶ms); + void cmdDisplayBottom(Common::Array<byte> ¶ms); + void cmdIfMapFlag(Common::Array<byte> ¶ms); + void cmdSelRndChar(Common::Array<byte> ¶ms); + void cmdGiveEnchanted(Common::Array<byte> ¶ms); + void cmdItemType(Common::Array<byte> ¶ms); + void cmdMakeNothingHere(Common::Array<byte> ¶ms); + void cmdNoAction2(Common::Array<byte> ¶ms); + void cmdChooseNumeric(Common::Array<byte> ¶ms); + void cmdDisplayBottomTwoLines(Common::Array<byte> ¶ms); + void cmdDisplayLarge(Common::Array<byte> ¶ms); + void cmdExchObj(Common::Array<byte> ¶ms); + void cmdFallToMap(Common::Array<byte> ¶ms); + void cmdDisplayMain(Common::Array<byte> ¶ms); + void cmdGoto(Common::Array<byte> ¶ms); + void cmdConfirmWord2(Common::Array<byte> ¶ms); + void cmdGotoRandom(Common::Array<byte> ¶ms); + void cmdCutsceneEndDarkside(Common::Array<byte> ¶ms); + void cmdCutsceneEdWorld(Common::Array<byte> ¶ms); + void cmdFlipWorld(Common::Array<byte> ¶ms); + void cmdPlayCD(Common::Array<byte> ¶ms); +public: + int _animCounter; + bool _eventSkipped; public: Scripts(XeenEngine *vm); -- cgit v1.2.3 From 1b264ed299fd87262c2cf228418ec606fdf75646 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 21 Jan 2015 21:51:45 -0500 Subject: XEEN: Implemented the first few script commands --- engines/xeen/interface.cpp | 5 +- engines/xeen/interface.h | 5 +- engines/xeen/scripts.cpp | 125 ++++++++++++++++++++++++++++++--------------- engines/xeen/scripts.h | 16 +++--- 4 files changed, 98 insertions(+), 53 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index e31b9e240a..4b4e88afec 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -734,7 +734,10 @@ void Interface::draw3d(bool updateFlag) { assembleBorder(); - // TODO: write strings + // Draw any on-screen text if flagged to do so + if (_upDoorText && combat._attackMonsters[0] == -1) { + screen._windows[3].writeString(_screenText); + } if (updateFlag) { screen._windows[1].update(); diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 37ac7be5be..87edb02c5d 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -71,8 +71,8 @@ private: bool _isAnimReset; byte _tillMove; int _overallFrame; - bool _upDoorText; int _steppingFX; + Common::String _interfaceText; void initDrawStructs(); @@ -105,7 +105,8 @@ private: bool checkMoveDirection(int key); public: int _intrIndex1; - Common::String _interfaceText; + Common::String _screenText; + bool _upDoorText; public: Interface(XeenEngine *vm); diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 50584a2551..44b5cb325e 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -87,7 +87,7 @@ void Scripts::checkEvents() { int var18 = 0; _itemType = 0; - int var4F = 0; + _var4F = 0; bool var50 = false; _whoWill = 0; Mode oldMode = _vm->_mode; @@ -101,7 +101,7 @@ void Scripts::checkEvents() { } do { - int var4 = 0; + _lineNum = 0; int varA = 0; _animCounter = 0; int var4E = 0; @@ -111,28 +111,33 @@ void Scripts::checkEvents() { _nEdamageType = 0; int var40 = -1; - // Break out of the events if there's an attacking monster - if (combat._attackMonsters[0] != -1) { - _eventSkipped = true; - break; - } - - _eventSkipped = false; - - for (uint eventIndex = 0; eventIndex < map._events.size(); ++eventIndex) { - MazeEvent &event = map._events[eventIndex]; + while (_lineNum >= 0) { + // Break out of the events if there's an attacking monster + if (combat._attackMonsters[0] != -1) { + _eventSkipped = true; + break; + } - if (event._position == pt && party._mazeDirection != (pt.x | pt.y)) { - if (event._direction == party._mazeDirection || event._direction == DIR_ALL) { - _vm->_mode = MODE_9; - intf._interfaceText = event._parameters.size() == 0 ? "" : - map._events._text[event._parameters[0]]; - doOpcode(event._opcode, event._parameters); + _eventSkipped = false; + uint eventIndex; + for (eventIndex = 0; eventIndex < map._events.size(); ++eventIndex) { + MazeEvent &event = map._events[eventIndex]; - } else { - var50 = true; + if (event._position == pt && party._mazeDirection != (pt.x | pt.y) + && event._line == _lineNum) { + if (event._direction == party._mazeDirection || event._direction == DIR_ALL) { + _vm->_mode = MODE_9; + _paramText = event._parameters.size() == 0 ? "" : + map._events._text[event._parameters[0]]; + doOpcode(event._opcode, event._parameters); + break; + } else { + var50 = true; + } } } + if (eventIndex == map._events.size()) + break; } } while (0); @@ -151,20 +156,20 @@ typedef void(Scripts::*ScriptMethodPtr)(Common::Array<byte> &); void Scripts::doOpcode(Opcode opcode, Common::Array<byte> ¶ms) { static const ScriptMethodPtr COMMAND_LIST[] = { - &Scripts::cmdNone, &Scripts::cmdDisplay0x01, &Scripts::cmdDoorTextSml, + nullptr, &Scripts::cmdDisplay1, &Scripts::cmdDoorTextSml, &Scripts::cmdDoorTextLrg, &Scripts::cmdSignText, - &Scripts::cmdNPC, &Scripts::cmdPlayFX, &Scripts::cmdTeleportAndExit, - &Scripts::cmdIf1, &Scripts::cmdIf2, &Scripts::cmdIf3, + &Scripts::cmdNPC, &Scripts::cmdPlayFX, &Scripts::cmdTeleport, + &Scripts::cmdIf, &Scripts::cmdIf, &Scripts::cmdIf, &Scripts::cmdMoveObj, &Scripts::cmdTakeOrGive, &Scripts::cmdNoAction, &Scripts::cmdRemove, &Scripts::cmdSetChar, &Scripts::cmdSpawn, &Scripts::cmdDoTownEvent, &Scripts::cmdExit, &Scripts::cmdAfterMap, &Scripts::cmdGiveExtended, &Scripts::cmdConfirmWord, &Scripts::cmdDamage, &Scripts::cmdJumpRnd, &Scripts::cmdAfterEvent, &Scripts::cmdCallEvent, - &Scripts::cmdReturn, &Scripts::cmdSetVar, &Scripts::cmdTakeOrGive2, - &Scripts::cmdTakeOrGive3, &Scripts::cmdCutsceneEndClouds, - &Scripts::cmdTeleportAndContinue, &Scripts::cmdWhoWill, + &Scripts::cmdReturn, &Scripts::cmdSetVar, &Scripts::cmdTakeOrGive, + &Scripts::cmdTakeOrGive, &Scripts::cmdCutsceneEndClouds, + &Scripts::cmdTeleport, &Scripts::cmdWhoWill, &Scripts::cmdRndDamage, &Scripts::cmdMoveWallObj, &Scripts::cmdAlterCellFlag, - &Scripts::cmdAlterHed, &Scripts::cmdDisplayStat, &Scripts::cmdTakeOrGive4, + &Scripts::cmdAlterHed, &Scripts::cmdDisplayStat, &Scripts::cmdTakeOrGive, &Scripts::cmdSeatTextSml, &Scripts::cmdPlayEventVoc, &Scripts::cmdDisplayBottom, &Scripts::cmdIfMapFlag, &Scripts::cmdSelRndChar, &Scripts::cmdGiveEnchanted, &Scripts::cmdItemType, &Scripts::cmdMakeNothingHere, &Scripts::cmdNoAction2, @@ -178,20 +183,64 @@ void Scripts::doOpcode(Opcode opcode, Common::Array<byte> ¶ms) { (this->*COMMAND_LIST[opcode])(params); } -void Scripts::cmdNone(Common::Array<byte> ¶ms) {} -void Scripts::cmdDisplay0x01(Common::Array<byte> ¶ms) {} -void Scripts::cmdDoorTextSml(Common::Array<byte> ¶ms) {} -void Scripts::cmdDoorTextLrg(Common::Array<byte> ¶ms) {} +/** + * Display a msesage on-screen + */ +void Scripts::cmdDisplay1(Common::Array<byte> ¶ms) { + Screen &screen = *_vm->_screen; + Common::String msg = Common::String::format("\r\x03c%s", _paramText.c_str()); + + screen._windows[12].close(); + if (screen._windows[38]._enabled) + screen._windows[38].open(); + screen._windows[38].writeString(msg); + screen._windows[38].update(); + + _var4F = true; + cmdNoAction(params); +} + +/** + * Displays a door text message using the small font + */ +void Scripts::cmdDoorTextSml(Common::Array<byte> ¶ms) { + Interface &intf = *_vm->_interface; + intf._screenText = Common::String::format("\x02\f08\x03c\t116\v025%s\x03l\fd\x01", + _paramText.c_str()); + intf._upDoorText = true; + intf.draw3d(true); + _var4F = true; + + cmdNoAction(params); +} + +/** + * Displays a door text message using the large font + */ +void Scripts::cmdDoorTextLrg(Common::Array<byte> ¶ms) { + Interface &intf = *_vm->_interface; + intf._screenText = Common::String::format("\f04\x03c\t116\v030%s\x03l\fd", + _paramText.c_str()); + intf._upDoorText = true; + intf.draw3d(true); + _var4F = true; + + cmdNoAction(params); +} + void Scripts::cmdSignText(Common::Array<byte> ¶ms) {} void Scripts::cmdNPC(Common::Array<byte> ¶ms) {} void Scripts::cmdPlayFX(Common::Array<byte> ¶ms) {} -void Scripts::cmdTeleportAndExit(Common::Array<byte> ¶ms) {} -void Scripts::cmdIf1(Common::Array<byte> ¶ms) {} -void Scripts::cmdIf2(Common::Array<byte> ¶ms) {} -void Scripts::cmdIf3(Common::Array<byte> ¶ms) {} +void Scripts::cmdTeleport(Common::Array<byte> ¶ms) {} +void Scripts::cmdIf(Common::Array<byte> ¶ms) {} void Scripts::cmdMoveObj(Common::Array<byte> ¶ms) {} void Scripts::cmdTakeOrGive(Common::Array<byte> ¶ms) {} -void Scripts::cmdNoAction(Common::Array<byte> ¶ms) {} + +void Scripts::cmdNoAction(Common::Array<byte> ¶ms) { + // Move to next line + _lineNum = _vm->_party->_partyDead ? -1 : _lineNum + 1; +} + void Scripts::cmdRemove(Common::Array<byte> ¶ms) {} void Scripts::cmdSetChar(Common::Array<byte> ¶ms) {} void Scripts::cmdSpawn(Common::Array<byte> ¶ms) {} @@ -206,17 +255,13 @@ void Scripts::cmdAfterEvent(Common::Array<byte> ¶ms) {} void Scripts::cmdCallEvent(Common::Array<byte> ¶ms) {} void Scripts::cmdReturn(Common::Array<byte> ¶ms) {} void Scripts::cmdSetVar(Common::Array<byte> ¶ms) {} -void Scripts::cmdTakeOrGive2(Common::Array<byte> ¶ms) {} -void Scripts::cmdTakeOrGive3(Common::Array<byte> ¶ms) {} void Scripts::cmdCutsceneEndClouds(Common::Array<byte> ¶ms) {} -void Scripts::cmdTeleportAndContinue(Common::Array<byte> ¶ms) {} void Scripts::cmdWhoWill(Common::Array<byte> ¶ms) {} void Scripts::cmdRndDamage(Common::Array<byte> ¶ms) {} void Scripts::cmdMoveWallObj(Common::Array<byte> ¶ms) {} void Scripts::cmdAlterCellFlag(Common::Array<byte> ¶ms) {} void Scripts::cmdAlterHed(Common::Array<byte> ¶ms) {} void Scripts::cmdDisplayStat(Common::Array<byte> ¶ms) {} -void Scripts::cmdTakeOrGive4(Common::Array<byte> ¶ms) {} void Scripts::cmdSeatTextSml(Common::Array<byte> ¶ms) {} void Scripts::cmdPlayEventVoc(Common::Array<byte> ¶ms) {} void Scripts::cmdDisplayBottom(Common::Array<byte> ¶ms) {} diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 2fbcf78b38..9690887a16 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -126,22 +126,22 @@ private: int _treasureItems; int _treasureGold; int _treasureGems; + int _lineNum; int _v2; + int _var4F; int _nEdamageType; + Common::String _paramText; void doOpcode(Opcode opcode, Common::Array<byte> ¶ms); - void cmdNone(Common::Array<byte> ¶ms); - void cmdDisplay0x01(Common::Array<byte> ¶ms); + void cmdDisplay1(Common::Array<byte> ¶ms); void cmdDoorTextSml(Common::Array<byte> ¶ms); void cmdDoorTextLrg(Common::Array<byte> ¶ms); void cmdSignText(Common::Array<byte> ¶ms); void cmdNPC(Common::Array<byte> ¶ms); void cmdPlayFX(Common::Array<byte> ¶ms); - void cmdTeleportAndExit(Common::Array<byte> ¶ms); - void cmdIf1(Common::Array<byte> ¶ms); - void cmdIf2(Common::Array<byte> ¶ms); - void cmdIf3(Common::Array<byte> ¶ms); + void cmdTeleport(Common::Array<byte> ¶ms); + void cmdIf(Common::Array<byte> ¶ms); void cmdMoveObj(Common::Array<byte> ¶ms); void cmdTakeOrGive(Common::Array<byte> ¶ms); void cmdNoAction(Common::Array<byte> ¶ms); @@ -159,17 +159,13 @@ private: void cmdCallEvent(Common::Array<byte> ¶ms); void cmdReturn(Common::Array<byte> ¶ms); void cmdSetVar(Common::Array<byte> ¶ms); - void cmdTakeOrGive2(Common::Array<byte> ¶ms); - void cmdTakeOrGive3(Common::Array<byte> ¶ms); void cmdCutsceneEndClouds(Common::Array<byte> ¶ms); - void cmdTeleportAndContinue(Common::Array<byte> ¶ms); void cmdWhoWill(Common::Array<byte> ¶ms); void cmdRndDamage(Common::Array<byte> ¶ms); void cmdMoveWallObj(Common::Array<byte> ¶ms); void cmdAlterCellFlag(Common::Array<byte> ¶ms); void cmdAlterHed(Common::Array<byte> ¶ms); void cmdDisplayStat(Common::Array<byte> ¶ms); - void cmdTakeOrGive4(Common::Array<byte> ¶ms); void cmdSeatTextSml(Common::Array<byte> ¶ms); void cmdPlayEventVoc(Common::Array<byte> ¶ms); void cmdDisplayBottom(Common::Array<byte> ¶ms); -- cgit v1.2.3 From 16a5a99c3aa615f5b69a8c4c1df987c906973990 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 21 Jan 2015 22:09:12 -0500 Subject: XEEN: Fix strings used by newly added script commands --- engines/xeen/scripts.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 44b5cb325e..3bf7a3104c 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -188,7 +188,7 @@ void Scripts::doOpcode(Opcode opcode, Common::Array<byte> ¶ms) { */ void Scripts::cmdDisplay1(Common::Array<byte> ¶ms) { Screen &screen = *_vm->_screen; - Common::String msg = Common::String::format("\r\x03c%s", _paramText.c_str()); + Common::String msg = Common::String::format("\r\x03""c%s", _paramText.c_str()); screen._windows[12].close(); if (screen._windows[38]._enabled) @@ -205,7 +205,7 @@ void Scripts::cmdDisplay1(Common::Array<byte> ¶ms) { */ void Scripts::cmdDoorTextSml(Common::Array<byte> ¶ms) { Interface &intf = *_vm->_interface; - intf._screenText = Common::String::format("\x02\f08\x03c\t116\v025%s\x03l\fd\x01", + intf._screenText = Common::String::format("\x02\f""08\x03""c\t116\v025%s\x03""l\fd""\x01", _paramText.c_str()); intf._upDoorText = true; intf.draw3d(true); @@ -219,7 +219,7 @@ void Scripts::cmdDoorTextSml(Common::Array<byte> ¶ms) { */ void Scripts::cmdDoorTextLrg(Common::Array<byte> ¶ms) { Interface &intf = *_vm->_interface; - intf._screenText = Common::String::format("\f04\x03c\t116\v030%s\x03l\fd", + intf._screenText = Common::String::format("\f04\x03""c\t116\v030%s\x03""l\fd", _paramText.c_str()); intf._upDoorText = true; intf.draw3d(true); -- cgit v1.2.3 From 4c0c40c25df79d9cbed6f401b83165d90ae3b4cd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 22 Jan 2015 07:53:33 -0500 Subject: XEEN: Shifted more logic for 3d view drawing from Interface to InterfaceMap --- engines/xeen/interface.cpp | 739 +--------------------------------------- engines/xeen/interface.h | 38 +-- engines/xeen/interface_map.cpp | 744 +++++++++++++++++++++++++++++++++++++++++ engines/xeen/interface_map.h | 37 +- engines/xeen/scripts.cpp | 58 +++- engines/xeen/scripts.h | 3 +- 6 files changed, 836 insertions(+), 783 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 4b4e88afec..31fe00b0b8 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -29,24 +29,9 @@ namespace Xeen { Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(vm) { Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], (SpriteResource *)nullptr); - _batUIFrame = 0; - _spotDoorsUIFrame = 0; - _dangerSenseUIFrame = 0; - _face1UIFrame = 0; - _face2UIFrame = 0; - _blessedUIFrame = 0; - _powerShieldUIFrame = 0; - _holyBonusUIFrame = 0; - _heroismUIFrame = 0; - _flipUIFrame = 0; _buttonsLoaded = false; _hiliteChar = -1; _intrIndex1 = 0; - _flag1 = false; - _isAnimReset = false; - _tillMove = 0; - _overallFrame = 0; - _upDoorText = false; _steppingFX = 0; Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); @@ -79,15 +64,10 @@ void Interface::initDrawStructs() { } void Interface::setup() { - _globalSprites.load("global.icn"); - _borderSprites.load("border.icn"); - _spellFxSprites.load("spellfx.icn"); - _fecpSprites.load("fecp.brd"); - _blessSprites.load("bless.icn"); + InterfaceMap::setup(); _restoreSprites.load("restorex.icn"); _hpSprites.load("hpbars.icn"); _uiSprites.load("inn.icn"); - _charPowSprites.load("charpow.icn"); // Get mappings to the active characters in the party _vm->_party->_activeParty.resize(_vm->_party->_partyCount); @@ -277,14 +257,6 @@ start: for (int i = 0; i < TOTAL_CHARACTERS; ++i) _charFaces[i].clear(); - _globalSprites.clear(); - _borderSprites.clear(); - _spellFxSprites.clear(); - _fecpSprites.clear(); - _blessSprites.clear(); - _restoreSprites.clear(); - _hpSprites.clear(); - _uiSprites.clear(); } void Interface::loadCharIcons() { @@ -307,114 +279,6 @@ void Interface::setupBackground() { assembleBorder(); } -void Interface::assembleBorder() { - Screen &screen = *_vm->_screen; - - // Draw the outer frame - _globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8)); - - // Draw the animating bat character used to show when levitate is active - _borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16, - Common::Point(0, 82)); - _batUIFrame = (_batUIFrame + 1) % 12; - - // Draw UI element to indicate whether can spot hidden doors - _borderSprites.draw(screen, - (_thinWall && _vm->_party->checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, - Common::Point(194, 91)); - _spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12; - - // Draw UI element to indicate whether can sense danger - _borderSprites.draw(screen, - (_vm->_dangerSenseAllowed && _vm->_party->checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40, - Common::Point(107, 9)); - _dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12; - - // Handle the face UI elements for indicating clairvoyance status - _face1UIFrame = (_face1UIFrame + 1) % 4; - if (_vm->_face1State == 0) - _face1UIFrame += 4; - else if (_vm->_face1State == 2) - _face1UIFrame = 0; - - _face2UIFrame = (_face2UIFrame + 1) % 4 + 12; - if (_vm->_face2State == 0) - _face2UIFrame += 252; - else if (_vm->_face2State == 2) - _face2UIFrame = 0; - - if (!_vm->_party->_clairvoyanceActive) { - _face1UIFrame = 0; - _face2UIFrame = 8; - } - - _borderSprites.draw(screen, _face1UIFrame, Common::Point(0, 32)); - _borderSprites.draw(screen, - screen._windows[10]._enabled || screen._windows[2]._enabled ? - 52 : _face2UIFrame, - Common::Point(215, 32)); - - // Draw resistence indicators - if (!screen._windows[10]._enabled && !screen._windows[2]._enabled - && screen._windows[38]._enabled) { - _fecpSprites.draw(screen, _vm->_party->_fireResistence ? 1 : 0, - Common::Point(2, 2)); - _fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 3 : 2, - Common::Point(219, 2)); - _fecpSprites.draw(screen, _vm->_party->_coldResistence ? 5 : 4, - Common::Point(2, 134)); - _fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 7 : 6, - Common::Point(219, 134)); - } else { - _fecpSprites.draw(screen, _vm->_party->_fireResistence ? 9 : 8, - Common::Point(8, 8)); - _fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 10 : 11, - Common::Point(219, 8)); - _fecpSprites.draw(screen, _vm->_party->_coldResistence ? 12 : 13, - Common::Point(8, 134)); - _fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 14 : 15, - Common::Point(219, 134)); - } - - // Draw UI element for blessed - _blessSprites.draw(screen, 16, Common::Point(33, 137)); - if (_vm->_party->_blessedActive) { - _blessedUIFrame = (_blessedUIFrame + 1) % 4; - _blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137)); - } - - // Draw UI element for power shield - if (_vm->_party->_powerShieldActive) { - _powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4; - _blessSprites.draw(screen, _powerShieldUIFrame + 4, - Common::Point(55, 137)); - } - - // Draw UI element for holy bonus - if (_vm->_party->_holyBonusActive) { - _holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4; - _blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137)); - } - - // Draw UI element for heroism - if (_vm->_party->_heroismActive) { - _heroismUIFrame = (_heroismUIFrame + 1) % 4; - _blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137)); - } - - // Draw direction character if direction sense is active - if (_vm->_party->checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) { - const char *dirText = DIRECTION_TEXT[_vm->_party->_mazeDirection]; - Common::String msg = Common::String::format( - "\002""08\003""c\013""139\011""116%c\014""d\001", *dirText); - screen._windows[0].writeString(msg); - } - - // Draw view frame - if (screen._windows[12]._enabled) - screen._windows[12].frame(); -} - void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag) { Common::String playerNames[4]; Common::String playerRaces[4]; @@ -535,228 +399,6 @@ void Interface::moveCharacterToRoster() { error("TODO"); } -void Interface::draw3d(bool updateFlag) { - Combat &combat = *_vm->_combat; - EventsManager &events = *_vm->_events; - Map &map = *_vm->_map; - Party &party = *_vm->_party; - Screen &screen = *_vm->_screen; - Scripts &scripts = *_vm->_scripts; - - if (screen._windows[11]._enabled) - return; - - _flipUIFrame = (_flipUIFrame + 1) % 4; - if (_flipUIFrame == 0) - _flipWater = !_flipWater; - if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_2) && - !_flag1 && _vm->_moveMonsters) { - if (--_tillMove == 0) - moveMonsters(); - } - - MazeObject &objObject = map._mobData._objects[_objNumber]; - Direction partyDirection = _vm->_party->_mazeDirection; - int objNum = _objNumber - 1; - - // Loop to update the frame numbers for each maze object, applying the animation frame - // limits as specified by the map's _animationInfo listing - for (uint idx = 0; idx < map._mobData._objects.size(); ++idx) { - MazeObject &mazeObject = map._mobData._objects[idx]; - AnimationEntry &animEntry = map._animationInfo[mazeObject._spriteId]; - int directionIndex = DIRECTION_ANIM_POSITIONS[mazeObject._direction][partyDirection]; - - if (_isAnimReset) { - mazeObject._frame = animEntry._frame1._frames[directionIndex]; - } else { - ++mazeObject._frame; - if ((int)idx == objNum && scripts._animCounter > 0 && ( - objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) || - objObject._spriteId == 58 || objObject._spriteId == 73)) { - if (mazeObject._frame > 4 || mazeObject._spriteId == 58) - mazeObject._frame = 1; - } else if (mazeObject._frame >= animEntry._frame2._frames[directionIndex]) { - mazeObject._frame = animEntry._frame1._frames[directionIndex]; - } - } - - mazeObject._flipped = animEntry._flipped._flags[directionIndex]; - } - - if (map._isOutdoors) { - error("TODO: draw3d outdoors handling"); - } else { - // Default all the parts of draw struct not to be drawn by default - for (int idx = 3; idx < _indoorList.size(); ++idx) - _indoorList[idx]._frame = -1; - - if (_flag1) { - for (int idx = 0; idx < 96; ++idx) { - if (_indoorList[79 + idx]._sprites != nullptr) { - _indoorList[79 + idx]._frame = 0; - } else if (_indoorList[111 + idx]._sprites != nullptr) { - _indoorList[111 + idx]._frame = 1; - } else if (_indoorList[135 + idx]._sprites != nullptr) { - _indoorList[135 + idx]._frame = 2; - } else if (_indoorList[162 + idx]._sprites != nullptr) { - _indoorList[162 + idx]._frame = 0; - } - } - } else if (_charsShooting) { - for (int idx = 0; idx < 96; ++idx) { - if (_indoorList[162 + idx]._sprites != nullptr) { - _indoorList[162 + idx]._frame = 0; - } else if (_indoorList[135 + idx]._sprites != nullptr) { - _indoorList[135 + idx]._frame = 1; - } else if (_indoorList[111 + idx]._sprites != nullptr) { - _indoorList[111 + idx]._frame = 2; - } else if (_indoorList[79 + idx]._sprites != nullptr) { - _indoorList[79 + idx]._frame = 0; - } - } - } - - setMazeBits(); - _isAnimReset = false; - const int INDOOR_INDEXES[3] = { 157, 151, 154 }; - const int INDOOR_COMBAT_POS[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } }; - const int INDOOR_COMBAT_POS2[4] = { 8, 6, 4, 2 }; - - // Double check this, since it's not being used? - //MazeObject &objObject = map._mobData._objects[_objNumber - 1]; - - for (int idx = 0; idx < 3; ++idx) { - DrawStruct &ds1 = _indoorList[INDOOR_INDEXES[idx]]; - DrawStruct &ds2 = _indoorList[INDOOR_INDEXES[idx] + 1]; - ds1._sprites = nullptr; - ds2._sprites = nullptr; - - if (combat._charsArray1[idx]) { - int posIndex= combat._attackMonsters[1] && !combat._attackMonsters[2] ? 1 : 0; - --combat._charsArray1[idx]; - - if (combat._monPow[idx]) { - ds1._x = INDOOR_COMBAT_POS[idx][0]; - ds1._frame = 0; - ds1._scale = combat._monsterScale[idx]; - if (ds1._scale == 0x8000) { - ds1._x /= 3; - ds1._y = 60; - } else { - ds1._y = 73; - } - - ds1._flags = SPRFLAG_4000 | SPRFLAG_2000; - ds1._sprites = &_charPowSprites; - } - - if (combat._elemPow[idx]) { - ds2._x = INDOOR_COMBAT_POS[idx][posIndex] + INDOOR_COMBAT_POS2[idx]; - ds2._frame = combat._elemPow[idx]; - ds2._scale = combat._elemScale[idx]; - if (ds2._scale == 0x8000) - ds2._x /= 3; - ds2._flags = SPRFLAG_4000 | SPRFLAG_2000; - ds2._sprites = &_charPowSprites; - } - } - } - - setIndoorsMonsters(); - setIndoorsObjects(); - setIndoorsWallPics(); - - _indoorList[161]._sprites = nullptr; - _indoorList[160]._sprites = nullptr; - _indoorList[159]._sprites = nullptr; - - // Handle attacking monsters - int monsterIndex = 0; - if (combat._attackMonsters[0] != -1 && map._mobData._monsters[combat._attackMonsters[0]]._frame >= 0) { - _indoorList[159] = _indoorList[156]; - _indoorList[160] = _indoorList[157]; - _indoorList[161] = _indoorList[158]; - _indoorList[158]._sprites = nullptr; - _indoorList[156]._sprites = nullptr; - _indoorList[157]._sprites = nullptr; - monsterIndex = 1; - } else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 0) { - _indoorList[159] = _indoorList[150]; - _indoorList[160] = _indoorList[151]; - _indoorList[161] = _indoorList[152]; - _indoorList[152]._sprites = nullptr; - _indoorList[151]._sprites = nullptr; - _indoorList[150]._sprites = nullptr; - monsterIndex = 2; - } else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 0) { - _indoorList[159] = _indoorList[153]; - _indoorList[160] = _indoorList[154]; - _indoorList[161] = _indoorList[155]; - _indoorList[153]._sprites = nullptr; - _indoorList[154]._sprites = nullptr; - _indoorList[155]._sprites = nullptr; - monsterIndex = 3; - } - - drawIndoors(); - - switch (monsterIndex) { - case 1: - _indoorList[156] = _indoorList[159]; - _indoorList[157] = _indoorList[160]; - _indoorList[158] = _indoorList[161]; - break; - case 2: - _indoorList[150] = _indoorList[159]; - _indoorList[151] = _indoorList[160]; - _indoorList[152] = _indoorList[161]; - break; - case 3: - _indoorList[153] = _indoorList[159]; - _indoorList[154] = _indoorList[160]; - _indoorList[155] = _indoorList[161]; - break; - default: - break; - } - } - - animate3d(); - drawMiniMap(); - - if (party._falling == 1) { - error("TODO: Indoor falling"); - } - - if (party._falling == 2) { - screen.saveBackground(1); - } - - assembleBorder(); - - // Draw any on-screen text if flagged to do so - if (_upDoorText && combat._attackMonsters[0] == -1) { - screen._windows[3].writeString(_screenText); - } - - if (updateFlag) { - screen._windows[1].update(); - screen._windows[3].update(); - } - - // TODO: more stuff - - _vm->_party->_stepped = false; - if (_vm->_mode == MODE_9) { - // TODO - } - events.wait(2); -} - -void Interface::animate3d() { - -} - void Interface::startup() { Screen &screen = *_vm->_screen; loadCharIcons(); @@ -792,10 +434,6 @@ void Interface::mainIconsPrint() { screen._windows[34].update(); } -void Interface::moveMonsters() { - -} - void Interface::setMainButtons() { clearButtons(); @@ -821,381 +459,6 @@ void Interface::setMainButtons() { addButton(Common::Rect(239, 47, 312, 57), Common::KEYCODE_3, &_iconSprites, false); } -void Interface::drawMiniMap() { - Map &map = *_vm->_map; - Party &party = *_vm->_party; - Screen &screen = *_vm->_screen; - Window &window1 = screen._windows[1]; - - if (screen._windows[2]._enabled || screen._windows[10]._enabled) - return; - if (!party._automapOn && !party._wizardEyeActive) { - // Draw the Might & Magic logo - _globalSprites.draw(window1, 5, Common::Point(232, 9)); - return; - } - - int v, frame; - int frame2 = _overallFrame * 2; - bool eyeActive = party._wizardEyeActive; - if (party._automapOn) - party._wizardEyeActive = false; - - if (map._isOutdoors) { - _globalSprites.draw(window1, 15, Common::Point(237, 12)); - - for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { - for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), - 4); - frame = map.mazeDataCurrent()._surfaceTypes[v]; - - if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, frame, Common::Point(xp, yp)); - } - } - } - - for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { - for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), - 4); - frame = map.mazeData()._wallTypes[v]; - - if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, frame + 16, Common::Point(xp, yp)); - } - } - } - - for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { - for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), - 4); - - if (v != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, v + 32, Common::Point(xp, yp)); - } - } - } - - // Draw the direction arrow - _globalSprites.draw(window1, party._mazeDirection + 1, - Common::Point(267, 36)); - } else { - frame2 = (frame2 + 2) % 8; - - // First draw the default surface bases for each cell to show - for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { - for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), - 0, 0xffff); - - if (v != INVALID_CELL && (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, 0, Common::Point(xp, yp)); - } - } - } - - // Draw correct surface bases for revealed tiles - for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { - for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), - 0, 0xffff); - int surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; - - if (v != INVALID_CELL && map._currentSurfaceId && - (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, surfaceId + 36, Common::Point(xp, yp)); - } - } - } - - v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0); - if (v != INVALID_CELL && map._currentSurfaceId && - (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, - map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, - Common::Point(232, 9)); - } - - // Handle drawing surface sprites partially clipped at the left edge - for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x - 4, party._mazePosition.y + yDiff), - 0, 0xffff); - - if (v != INVALID_CELL && map._currentSurfaceId && - (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, - map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, - Common::Point(232, yp)); - } - } - - // Handle drawing surface sprites partially clipped at the top edge - for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, ++xDiff, xp += 8) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + 4), - 0, 0xffff); - - if (v != INVALID_CELL && map._currentSurfaceId && - (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, - map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, - Common::Point(xp, 9)); - } - } - - // - for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE; - ++idx, ++xDiff, xp += 10, yp -= 8) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x - 4, party._mazePosition.y - 3 + idx), - 12, 0xffff); - - switch (v) { - case 1: - frame = 18; - break; - case 3: - frame = 22; - break; - case 4: - case 13: - frame = 16; - break; - case 5: - case 8: - frame = 2; - break; - case 6: - frame = 30; - break; - case 7: - frame = 32; - break; - case 9: - frame = 24; - break; - case 10: - frame = 28; - break; - case 11: - frame = 14; - break; - case 12: - frame = frame2 + 4; - break; - case 14: - frame = 24; - break; - case 15: - frame = 26; - break; - default: - frame = -1; - break; - } - - if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) - map._tileSprites.draw(window1, frame, Common::Point(222, yp)); - - v = map.mazeLookup( - Common::Point(party._mazePosition.x - 3 + idx, party._mazePosition.y + 4), - 0); - - switch (v) { - case 1: - frame = 19; - break; - case 2: - frame = 35; - break; - case 3: - frame = 23; - break; - case 4: - case 13: - frame = 17; - break; - case 5: - case 8: - frame = 3; - break; - case 6: - frame = 31; - break; - case 7: - frame = 33; - break; - case 9: - frame = 21; - break; - case 10: - frame = 29; - break; - case 11: - frame = 15; - break; - case 12: - frame = frame2 + 5; - break; - case 14: - frame = 25; - break; - case 15: - frame = 27; - break; - default: - frame = -1; - break; - } - - if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) - map._tileSprites.draw(window1, frame, Common::Point(xp, 4)); - } - - // Draw the front/back walls of cells in the minimap - for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; - ++rowNum, --yDiff, yp += 8) { - for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; - ++colNum, ++xDiff, xp += 10) { - if (colNum == 4 && rowNum == 4) { - // Center of the minimap. Draw the direction arrow - _globalSprites.draw(window1, party._mazeDirection + 1, - Common::Point(272, 40)); - } - - v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff, - party._mazePosition.y + yDiff), 12, 0xffff); - switch (v) { - case 1: - frame = 18; - break; - case 3: - frame = 22; - break; - case 4: - case 13: - frame = 16; - break; - case 5: - case 8: - frame = 2; - break; - case 6: - frame = 30; - break; - case 7: - frame = 32; - break; - case 9: - frame = 20; - break; - case 10: - frame = 28; - break; - case 11: - frame = 14; - break; - case 12: - frame = frame2 + 4; - break; - case 14: - frame = 24; - break; - case 15: - frame = 26; - break; - default: - frame = -1; - break; - } - - if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, frame, Common::Point(xp, yp)); - } - - v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff, - party._mazePosition.y + yDiff), 12, 0xffff); - switch (v) { - case 1: - frame = 19; - break; - case 2: - frame = 35; - break; - case 3: - frame = 23; - break; - case 4: - case 13: - frame = 17; - break; - case 5: - case 8: - frame = 3; - break; - case 6: - frame = 31; - break; - case 7: - frame = 33; - break; - case 9: - frame = 21; - break; - case 10: - frame = 29; - break; - case 11: - frame = 15; - break; - case 12: - frame = frame2 + 5; - break; - case 14: - frame = 25; - break; - case 15: - frame = 27; - break; - default: - frame = -1; - break; - } - - if (v == -1 && (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, frame, Common::Point(xp, yp)); - } - } - } - - // Draw the top of blocked/wall cells on the map - for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { - for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), - 0, 0xffff); - - if (v == INVALID_CELL || (!map._currentSteppedOn && !party._wizardEyeActive)) { - map._tileSprites.draw(window1, 1, Common::Point(xp, yp)); - } - } - } - } - - // Draw outer rectangle around the automap - _globalSprites.draw(window1, 6, Common::Point(223, 3)); - party._wizardEyeActive = eyeActive; -} - /** * Waits for a keypress or click, whilst still allowing the game scene to * be animated. diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 87edb02c5d..28f2bbee75 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -38,39 +38,19 @@ class XeenEngine; class Interface: public ButtonContainer, public InterfaceMap { private: XeenEngine *_vm; - SpriteResource _dseFace; - SpriteResource _globalSprites; - SpriteResource _borderSprites; - SpriteResource _spellFxSprites; - SpriteResource _fecpSprites; - SpriteResource _blessSprites; SpriteResource _restoreSprites; + SpriteResource _dseFace; SpriteResource _hpSprites; SpriteResource _uiSprites; SpriteResource _iconSprites; - SpriteResource _charPowSprites; SpriteResource _charFaces[TOTAL_CHARACTERS]; SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; DrawStruct _faceDrawStructs[4]; DrawStruct _mainList[16]; int _combatCharIds[8]; - int _batUIFrame; - int _spotDoorsUIFrame; - int _dangerSenseUIFrame; - int _face1UIFrame; - int _face2UIFrame; - int _blessedUIFrame; - int _powerShieldUIFrame; - int _holyBonusUIFrame; - int _heroismUIFrame; - int _flipUIFrame; bool _buttonsLoaded; int _hiliteChar; - bool _flag1; - bool _isAnimReset; - byte _tillMove; - int _overallFrame; int _steppingFX; Common::String _interfaceText; @@ -78,8 +58,6 @@ private: void loadSprites(); - void assembleBorder(); - void setupBackground(); void setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag); @@ -88,14 +66,8 @@ private: void moveCharacterToRoster(); - void animate3d(); - - void moveMonsters(); - void setMainButtons(); - void drawMiniMap(); - void chargeStep(); void stepTime(); @@ -105,12 +77,12 @@ private: bool checkMoveDirection(int key); public: int _intrIndex1; - Common::String _screenText; - bool _upDoorText; public: Interface(XeenEngine *vm); - void setup(); + virtual ~Interface() {} + + virtual void setup(); void manageCharacters(bool soundPlayed); @@ -118,8 +90,6 @@ public: void loadPartyIcons(); - void draw3d(bool updateFlag); - void startup(); void mainIconsPrint(); diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 4ff64b38eb..be344aef22 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -374,9 +374,266 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) { _objNumber = 0; _combatFloatCounter = 0; _thinWall = false; + _isAnimReset = false; + _upDoorText = false; + _batUIFrame = 0; + _spotDoorsUIFrame = 0; + _dangerSenseUIFrame = 0; + _face1UIFrame = 0; + _face2UIFrame = 0; + _blessedUIFrame = 0; + _powerShieldUIFrame = 0; + _holyBonusUIFrame = 0; + _heroismUIFrame = 0; + _flipUIFrame = 0; + _tillMove = 0; + _flag1 = false; + _overallFrame = 0; +} + +void InterfaceMap::setup() { + _globalSprites.load("global.icn"); + _borderSprites.load("border.icn"); + _spellFxSprites.load("spellfx.icn"); + _fecpSprites.load("fecp.brd"); + _blessSprites.load("bless.icn"); + _charPowSprites.load("charpow.icn"); } +void InterfaceMap::draw3d(bool updateFlag) { + Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + Scripts &scripts = *_vm->_scripts; + + if (screen._windows[11]._enabled) + return; + + _flipUIFrame = (_flipUIFrame + 1) % 4; + if (_flipUIFrame == 0) + _flipWater = !_flipWater; + if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_2) && + !_flag1 && _vm->_moveMonsters) { + if (--_tillMove == 0) + moveMonsters(); + } + + MazeObject &objObject = map._mobData._objects[_objNumber]; + Direction partyDirection = _vm->_party->_mazeDirection; + int objNum = _objNumber - 1; + + // Loop to update the frame numbers for each maze object, applying the animation frame + // limits as specified by the map's _animationInfo listing + for (uint idx = 0; idx < map._mobData._objects.size(); ++idx) { + MazeObject &mazeObject = map._mobData._objects[idx]; + AnimationEntry &animEntry = map._animationInfo[mazeObject._spriteId]; + int directionIndex = DIRECTION_ANIM_POSITIONS[mazeObject._direction][partyDirection]; + + if (_isAnimReset) { + mazeObject._frame = animEntry._frame1._frames[directionIndex]; + } + else { + ++mazeObject._frame; + if ((int)idx == objNum && scripts._animCounter > 0 && ( + objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) || + objObject._spriteId == 58 || objObject._spriteId == 73)) { + if (mazeObject._frame > 4 || mazeObject._spriteId == 58) + mazeObject._frame = 1; + } + else if (mazeObject._frame >= animEntry._frame2._frames[directionIndex]) { + mazeObject._frame = animEntry._frame1._frames[directionIndex]; + } + } + + mazeObject._flipped = animEntry._flipped._flags[directionIndex]; + } + + if (map._isOutdoors) { + error("TODO: draw3d outdoors handling"); + } + else { + // Default all the parts of draw struct not to be drawn by default + for (int idx = 3; idx < _indoorList.size(); ++idx) + _indoorList[idx]._frame = -1; + + if (_flag1) { + for (int idx = 0; idx < 96; ++idx) { + if (_indoorList[79 + idx]._sprites != nullptr) { + _indoorList[79 + idx]._frame = 0; + } + else if (_indoorList[111 + idx]._sprites != nullptr) { + _indoorList[111 + idx]._frame = 1; + } + else if (_indoorList[135 + idx]._sprites != nullptr) { + _indoorList[135 + idx]._frame = 2; + } + else if (_indoorList[162 + idx]._sprites != nullptr) { + _indoorList[162 + idx]._frame = 0; + } + } + } + else if (_charsShooting) { + for (int idx = 0; idx < 96; ++idx) { + if (_indoorList[162 + idx]._sprites != nullptr) { + _indoorList[162 + idx]._frame = 0; + } + else if (_indoorList[135 + idx]._sprites != nullptr) { + _indoorList[135 + idx]._frame = 1; + } + else if (_indoorList[111 + idx]._sprites != nullptr) { + _indoorList[111 + idx]._frame = 2; + } + else if (_indoorList[79 + idx]._sprites != nullptr) { + _indoorList[79 + idx]._frame = 0; + } + } + } + + setMazeBits(); + _isAnimReset = false; + const int INDOOR_INDEXES[3] = { 157, 151, 154 }; + const int INDOOR_COMBAT_POS[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } }; + const int INDOOR_COMBAT_POS2[4] = { 8, 6, 4, 2 }; + + // Double check this, since it's not being used? + //MazeObject &objObject = map._mobData._objects[_objNumber - 1]; + + for (int idx = 0; idx < 3; ++idx) { + DrawStruct &ds1 = _indoorList[INDOOR_INDEXES[idx]]; + DrawStruct &ds2 = _indoorList[INDOOR_INDEXES[idx] + 1]; + ds1._sprites = nullptr; + ds2._sprites = nullptr; + + if (combat._charsArray1[idx]) { + int posIndex = combat._attackMonsters[1] && !combat._attackMonsters[2] ? 1 : 0; + --combat._charsArray1[idx]; + + if (combat._monPow[idx]) { + ds1._x = INDOOR_COMBAT_POS[idx][0]; + ds1._frame = 0; + ds1._scale = combat._monsterScale[idx]; + if (ds1._scale == 0x8000) { + ds1._x /= 3; + ds1._y = 60; + } + else { + ds1._y = 73; + } + + ds1._flags = SPRFLAG_4000 | SPRFLAG_2000; + ds1._sprites = &_charPowSprites; + } + if (combat._elemPow[idx]) { + ds2._x = INDOOR_COMBAT_POS[idx][posIndex] + INDOOR_COMBAT_POS2[idx]; + ds2._frame = combat._elemPow[idx]; + ds2._scale = combat._elemScale[idx]; + if (ds2._scale == 0x8000) + ds2._x /= 3; + ds2._flags = SPRFLAG_4000 | SPRFLAG_2000; + ds2._sprites = &_charPowSprites; + } + } + } + + setIndoorsMonsters(); + setIndoorsObjects(); + setIndoorsWallPics(); + + _indoorList[161]._sprites = nullptr; + _indoorList[160]._sprites = nullptr; + _indoorList[159]._sprites = nullptr; + + // Handle attacking monsters + int monsterIndex = 0; + if (combat._attackMonsters[0] != -1 && map._mobData._monsters[combat._attackMonsters[0]]._frame >= 0) { + _indoorList[159] = _indoorList[156]; + _indoorList[160] = _indoorList[157]; + _indoorList[161] = _indoorList[158]; + _indoorList[158]._sprites = nullptr; + _indoorList[156]._sprites = nullptr; + _indoorList[157]._sprites = nullptr; + monsterIndex = 1; + } + else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 0) { + _indoorList[159] = _indoorList[150]; + _indoorList[160] = _indoorList[151]; + _indoorList[161] = _indoorList[152]; + _indoorList[152]._sprites = nullptr; + _indoorList[151]._sprites = nullptr; + _indoorList[150]._sprites = nullptr; + monsterIndex = 2; + } + else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 0) { + _indoorList[159] = _indoorList[153]; + _indoorList[160] = _indoorList[154]; + _indoorList[161] = _indoorList[155]; + _indoorList[153]._sprites = nullptr; + _indoorList[154]._sprites = nullptr; + _indoorList[155]._sprites = nullptr; + monsterIndex = 3; + } + + drawIndoors(); + + switch (monsterIndex) { + case 1: + _indoorList[156] = _indoorList[159]; + _indoorList[157] = _indoorList[160]; + _indoorList[158] = _indoorList[161]; + break; + case 2: + _indoorList[150] = _indoorList[159]; + _indoorList[151] = _indoorList[160]; + _indoorList[152] = _indoorList[161]; + break; + case 3: + _indoorList[153] = _indoorList[159]; + _indoorList[154] = _indoorList[160]; + _indoorList[155] = _indoorList[161]; + break; + default: + break; + } + } + + animate3d(); + drawMiniMap(); + + if (party._falling == 1) { + error("TODO: Indoor falling"); + } + + if (party._falling == 2) { + screen.saveBackground(1); + } + + assembleBorder(); + + // Draw any on-screen text if flagged to do so + if (_upDoorText && combat._attackMonsters[0] == -1) { + screen._windows[3].writeString(_screenText); + } + + if (updateFlag) { + screen._windows[1].update(); + screen._windows[3].update(); + } + + // TODO: more stuff + + _vm->_party->_stepped = false; + if (_vm->_mode == MODE_9) { + // TODO + } + events.wait(2); +} + +void InterfaceMap::animate3d() { + +} void InterfaceMap::setMazeBits() { Common::fill(&_wo[0], &_wo[308], 0); @@ -3453,4 +3710,491 @@ void InterfaceMap::drawIndoors() { _charsShooting = _isShooting; } +void InterfaceMap::moveMonsters() { + // TODO +} + +void InterfaceMap::assembleBorder() { + Screen &screen = *_vm->_screen; + + // Draw the outer frame + _globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8)); + + // Draw the animating bat character used to show when levitate is active + _borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16, + Common::Point(0, 82)); + _batUIFrame = (_batUIFrame + 1) % 12; + + // Draw UI element to indicate whether can spot hidden doors + _borderSprites.draw(screen, + (_thinWall && _vm->_party->checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, + Common::Point(194, 91)); + _spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12; + + // Draw UI element to indicate whether can sense danger + _borderSprites.draw(screen, + (_vm->_dangerSenseAllowed && _vm->_party->checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40, + Common::Point(107, 9)); + _dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12; + + // Handle the face UI elements for indicating clairvoyance status + _face1UIFrame = (_face1UIFrame + 1) % 4; + if (_vm->_face1State == 0) + _face1UIFrame += 4; + else if (_vm->_face1State == 2) + _face1UIFrame = 0; + + _face2UIFrame = (_face2UIFrame + 1) % 4 + 12; + if (_vm->_face2State == 0) + _face2UIFrame += 252; + else if (_vm->_face2State == 2) + _face2UIFrame = 0; + + if (!_vm->_party->_clairvoyanceActive) { + _face1UIFrame = 0; + _face2UIFrame = 8; + } + + _borderSprites.draw(screen, _face1UIFrame, Common::Point(0, 32)); + _borderSprites.draw(screen, + screen._windows[10]._enabled || screen._windows[2]._enabled ? + 52 : _face2UIFrame, + Common::Point(215, 32)); + + // Draw resistence indicators + if (!screen._windows[10]._enabled && !screen._windows[2]._enabled + && screen._windows[38]._enabled) { + _fecpSprites.draw(screen, _vm->_party->_fireResistence ? 1 : 0, + Common::Point(2, 2)); + _fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 3 : 2, + Common::Point(219, 2)); + _fecpSprites.draw(screen, _vm->_party->_coldResistence ? 5 : 4, + Common::Point(2, 134)); + _fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 7 : 6, + Common::Point(219, 134)); + } else { + _fecpSprites.draw(screen, _vm->_party->_fireResistence ? 9 : 8, + Common::Point(8, 8)); + _fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 10 : 11, + Common::Point(219, 8)); + _fecpSprites.draw(screen, _vm->_party->_coldResistence ? 12 : 13, + Common::Point(8, 134)); + _fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 14 : 15, + Common::Point(219, 134)); + } + + // Draw UI element for blessed + _blessSprites.draw(screen, 16, Common::Point(33, 137)); + if (_vm->_party->_blessedActive) { + _blessedUIFrame = (_blessedUIFrame + 1) % 4; + _blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137)); + } + + // Draw UI element for power shield + if (_vm->_party->_powerShieldActive) { + _powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4; + _blessSprites.draw(screen, _powerShieldUIFrame + 4, + Common::Point(55, 137)); + } + + // Draw UI element for holy bonus + if (_vm->_party->_holyBonusActive) { + _holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4; + _blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137)); + } + + // Draw UI element for heroism + if (_vm->_party->_heroismActive) { + _heroismUIFrame = (_heroismUIFrame + 1) % 4; + _blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137)); + } + + // Draw direction character if direction sense is active + if (_vm->_party->checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) { + const char *dirText = DIRECTION_TEXT[_vm->_party->_mazeDirection]; + Common::String msg = Common::String::format( + "\002""08\003""c\013""139\011""116%c\014""d\001", *dirText); + screen._windows[0].writeString(msg); + } + + // Draw view frame + if (screen._windows[12]._enabled) + screen._windows[12].frame(); +} + +void InterfaceMap::drawMiniMap() { + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + Window &window1 = screen._windows[1]; + + if (screen._windows[2]._enabled || screen._windows[10]._enabled) + return; + if (!party._automapOn && !party._wizardEyeActive) { + // Draw the Might & Magic logo + _globalSprites.draw(window1, 5, Common::Point(232, 9)); + return; + } + + int v, frame; + int frame2 = _overallFrame * 2; + bool eyeActive = party._wizardEyeActive; + if (party._automapOn) + party._wizardEyeActive = false; + + if (map._isOutdoors) { + _globalSprites.draw(window1, 15, Common::Point(237, 12)); + + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 4); + frame = map.mazeDataCurrent()._surfaceTypes[v]; + + if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, frame, Common::Point(xp, yp)); + } + } + } + + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 4); + frame = map.mazeData()._wallTypes[v]; + + if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, frame + 16, Common::Point(xp, yp)); + } + } + } + + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 4); + + if (v != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, v + 32, Common::Point(xp, yp)); + } + } + } + + // Draw the direction arrow + _globalSprites.draw(window1, party._mazeDirection + 1, + Common::Point(267, 36)); + } else { + frame2 = (frame2 + 2) % 8; + + // First draw the default surface bases for each cell to show + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 0, 0xffff); + + if (v != INVALID_CELL && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, 0, Common::Point(xp, yp)); + } + } + } + + // Draw correct surface bases for revealed tiles + for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 0, 0xffff); + int surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; + + if (v != INVALID_CELL && map._currentSurfaceId && + (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, surfaceId + 36, Common::Point(xp, yp)); + } + } + } + + v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0); + if (v != INVALID_CELL && map._currentSurfaceId && + (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, + map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, + Common::Point(232, 9)); + } + + // Handle drawing surface sprites partially clipped at the left edge + for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x - 4, party._mazePosition.y + yDiff), + 0, 0xffff); + + if (v != INVALID_CELL && map._currentSurfaceId && + (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, + map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, + Common::Point(232, yp)); + } + } + + // Handle drawing surface sprites partially clipped at the top edge + for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, ++xDiff, xp += 8) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + 4), + 0, 0xffff); + + if (v != INVALID_CELL && map._currentSurfaceId && + (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, + map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, + Common::Point(xp, 9)); + } + } + + // + for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE; + ++idx, ++xDiff, xp += 10, yp -= 8) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x - 4, party._mazePosition.y - 3 + idx), + 12, 0xffff); + + switch (v) { + case 1: + frame = 18; + break; + case 3: + frame = 22; + break; + case 4: + case 13: + frame = 16; + break; + case 5: + case 8: + frame = 2; + break; + case 6: + frame = 30; + break; + case 7: + frame = 32; + break; + case 9: + frame = 24; + break; + case 10: + frame = 28; + break; + case 11: + frame = 14; + break; + case 12: + frame = frame2 + 4; + break; + case 14: + frame = 24; + break; + case 15: + frame = 26; + break; + default: + frame = -1; + break; + } + + if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) + map._tileSprites.draw(window1, frame, Common::Point(222, yp)); + + v = map.mazeLookup( + Common::Point(party._mazePosition.x - 3 + idx, party._mazePosition.y + 4), + 0); + + switch (v) { + case 1: + frame = 19; + break; + case 2: + frame = 35; + break; + case 3: + frame = 23; + break; + case 4: + case 13: + frame = 17; + break; + case 5: + case 8: + frame = 3; + break; + case 6: + frame = 31; + break; + case 7: + frame = 33; + break; + case 9: + frame = 21; + break; + case 10: + frame = 29; + break; + case 11: + frame = 15; + break; + case 12: + frame = frame2 + 5; + break; + case 14: + frame = 25; + break; + case 15: + frame = 27; + break; + default: + frame = -1; + break; + } + + if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) + map._tileSprites.draw(window1, frame, Common::Point(xp, 4)); + } + + // Draw the front/back walls of cells in the minimap + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; + ++rowNum, --yDiff, yp += 8) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; + ++colNum, ++xDiff, xp += 10) { + if (colNum == 4 && rowNum == 4) { + // Center of the minimap. Draw the direction arrow + _globalSprites.draw(window1, party._mazeDirection + 1, + Common::Point(272, 40)); + } + + v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff, + party._mazePosition.y + yDiff), 12, 0xffff); + switch (v) { + case 1: + frame = 18; + break; + case 3: + frame = 22; + break; + case 4: + case 13: + frame = 16; + break; + case 5: + case 8: + frame = 2; + break; + case 6: + frame = 30; + break; + case 7: + frame = 32; + break; + case 9: + frame = 20; + break; + case 10: + frame = 28; + break; + case 11: + frame = 14; + break; + case 12: + frame = frame2 + 4; + break; + case 14: + frame = 24; + break; + case 15: + frame = 26; + break; + default: + frame = -1; + break; + } + + if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, frame, Common::Point(xp, yp)); + } + + v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff, + party._mazePosition.y + yDiff), 12, 0xffff); + switch (v) { + case 1: + frame = 19; + break; + case 2: + frame = 35; + break; + case 3: + frame = 23; + break; + case 4: + case 13: + frame = 17; + break; + case 5: + case 8: + frame = 3; + break; + case 6: + frame = 31; + break; + case 7: + frame = 33; + break; + case 9: + frame = 21; + break; + case 10: + frame = 29; + break; + case 11: + frame = 15; + break; + case 12: + frame = frame2 + 5; + break; + case 14: + frame = 25; + break; + case 15: + frame = 27; + break; + default: + frame = -1; + break; + } + + if (v == -1 && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, frame, Common::Point(xp, yp)); + } + } + } + + // Draw the top of blocked/wall cells on the map + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 0, 0xffff); + + if (v == INVALID_CELL || (!map._currentSteppedOn && !party._wizardEyeActive)) { + map._tileSprites.draw(window1, 1, Common::Point(xp, yp)); + } + } + } + } + + // Draw outer rectangle around the automap + _globalSprites.draw(window1, 6, Common::Point(223, 3)); + party._wizardEyeActive = eyeActive; +} + } // End of namespace Xeen diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 189598bb5c..12e5ac6410 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -83,6 +83,11 @@ public: class InterfaceMap { private: XeenEngine *_vm; + SpriteResource _borderSprites; + SpriteResource _spellFxSprites; + SpriteResource _fecpSprites; + SpriteResource _blessSprites; + SpriteResource _charPowSprites; int _combatFloatCounter; void initDrawStructs(); @@ -90,9 +95,9 @@ private: void setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, SpriteResource *sprites, int frame, int defaultY); protected: + SpriteResource _globalSprites; int8 _wp[20]; byte _wo[308]; - int _overallFrame; bool _flipWater; bool _flipGround; bool _flipSky; @@ -101,14 +106,44 @@ protected: bool _charsShooting; int _objNumber; bool _thinWall; + bool _isAnimReset; + int _batUIFrame; + int _spotDoorsUIFrame; + int _dangerSenseUIFrame; + int _face1UIFrame; + int _face2UIFrame; + int _blessedUIFrame; + int _powerShieldUIFrame; + int _holyBonusUIFrame; + int _heroismUIFrame; + int _flipUIFrame; + byte _tillMove; + bool _flag1; + int _overallFrame; void setMazeBits(); + + void animate3d(); + + void moveMonsters(); + + void drawMiniMap(); + + void assembleBorder(); + + virtual void setup(); public: OutdoorDrawList _outdoorList; IndoorDrawList _indoorList; + bool _upDoorText; + Common::String _screenText; public: InterfaceMap(XeenEngine *vm); + virtual ~InterfaceMap() {} + + void draw3d(bool updateFlag); + void setIndoorsMonsters(); void setIndoorsObjects(); diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 3bf7a3104c..73c0445011 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -129,7 +129,7 @@ void Scripts::checkEvents() { _vm->_mode = MODE_9; _paramText = event._parameters.size() == 0 ? "" : map._events._text[event._parameters[0]]; - doOpcode(event._opcode, event._parameters); + doOpcode(event); break; } else { var50 = true; @@ -154,7 +154,10 @@ void Scripts::openGrate(int v1, int v2) { typedef void(Scripts::*ScriptMethodPtr)(Common::Array<byte> &); -void Scripts::doOpcode(Opcode opcode, Common::Array<byte> ¶ms) { +/** + * Handles executing a given script command + */ +void Scripts::doOpcode(MazeEvent &event) { static const ScriptMethodPtr COMMAND_LIST[] = { nullptr, &Scripts::cmdDisplay1, &Scripts::cmdDoorTextSml, &Scripts::cmdDoorTextLrg, &Scripts::cmdSignText, @@ -180,7 +183,8 @@ void Scripts::doOpcode(Opcode opcode, Common::Array<byte> ¶ms) { &Scripts::cmdCutsceneEdWorld, &Scripts::cmdFlipWorld, &Scripts::cmdPlayCD }; - (this->*COMMAND_LIST[opcode])(params); + _event = &event; + (this->*COMMAND_LIST[event._opcode])(event._parameters); } /** @@ -209,8 +213,8 @@ void Scripts::cmdDoorTextSml(Common::Array<byte> ¶ms) { _paramText.c_str()); intf._upDoorText = true; intf.draw3d(true); - _var4F = true; + _var4F = true; cmdNoAction(params); } @@ -223,16 +227,52 @@ void Scripts::cmdDoorTextLrg(Common::Array<byte> ¶ms) { _paramText.c_str()); intf._upDoorText = true; intf.draw3d(true); + _var4F = true; + cmdNoAction(params); +} +void Scripts::cmdSignText(Common::Array<byte> ¶ms) { + Interface &intf = *_vm->_interface; + intf._screenText = Common::String::format("\f08\x03""c\t120\v088%s\x03""l\fd", + _paramText.c_str()); + intf._upDoorText = true; + intf.draw3d(true); + + _var4F = true; cmdNoAction(params); } -void Scripts::cmdSignText(Common::Array<byte> ¶ms) {} -void Scripts::cmdNPC(Common::Array<byte> ¶ms) {} -void Scripts::cmdPlayFX(Common::Array<byte> ¶ms) {} -void Scripts::cmdTeleport(Common::Array<byte> ¶ms) {} -void Scripts::cmdIf(Common::Array<byte> ¶ms) {} +void Scripts::cmdNPC(Common::Array<byte> ¶ms) { + warning("TODO: cmdNPC"); +} + +void Scripts::cmdPlayFX(Common::Array<byte> ¶ms) { + _vm->_sound->playFX(params[0]); + + _var4F = true; + cmdNoAction(params); +} + +void Scripts::cmdTeleport(Common::Array<byte> ¶ms) { +} + +void Scripts::cmdIf(Common::Array<byte> ¶ms) { + switch (params[0]) { + case 16: + case 34: + case 100: + break; + case 25: + case 35: + case 101: + case 106: + break; + default: + break; + } +} + void Scripts::cmdMoveObj(Common::Array<byte> ¶ms) {} void Scripts::cmdTakeOrGive(Common::Array<byte> ¶ms) {} diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 9690887a16..808566af39 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -132,8 +132,9 @@ private: int _var4F; int _nEdamageType; Common::String _paramText; + MazeEvent *_event; - void doOpcode(Opcode opcode, Common::Array<byte> ¶ms); + void doOpcode(MazeEvent &event); void cmdDisplay1(Common::Array<byte> ¶ms); void cmdDoorTextSml(Common::Array<byte> ¶ms); void cmdDoorTextLrg(Common::Array<byte> ¶ms); -- cgit v1.2.3 From b597d71bcdd7792df1cc53d8354f700b0dc4ab72 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 22 Jan 2015 19:41:55 -0500 Subject: XEEN: Implemented animate3d --- engines/xeen/combat.cpp | 2 +- engines/xeen/combat.h | 2 +- engines/xeen/interface_map.cpp | 117 ++++++++++++++++++++++++++++++++++++++++- engines/xeen/interface_map.h | 8 +++ engines/xeen/map.cpp | 3 ++ engines/xeen/map.h | 3 ++ 6 files changed, 131 insertions(+), 4 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 98dff4c6d9..4d3cb53bf9 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -32,7 +32,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm) { Common::fill(&_monsterScale[0], &_monsterScale[12], 0); Common::fill(&_elemPow[0], &_elemPow[12], 0); Common::fill(&_elemScale[0], &_elemScale[12], 0); - Common::fill(&_shooting[0], &_shooting[6], 0); + Common::fill(&_shooting[0], &_shooting[8], 0); } void Combat::clear() { diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 8e54353212..882f90e604 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -57,7 +57,7 @@ public: int _monsterScale[12]; int _elemPow[12]; int _elemScale[12]; - bool _shooting[6]; + bool _shooting[8]; public: Combat(XeenEngine *vm); diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index be344aef22..70297be5af 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -27,7 +27,9 @@ namespace Xeen { -OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]) { +OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]), + _combatImgs1(&_data[124]), _combatImgs2(&_data[95]), + _combatImgs3(&_data[76]), _combatImgs4(&_data[53]) { _data[0] = DrawStruct(0, 8, 8); _data[1] = DrawStruct(1, 8, 25); _data[2] = DrawStruct(0, 8, 67); @@ -185,7 +187,9 @@ IndoorDrawList::IndoorDrawList() : _objects0(_data[149]), _objects1(_data[125]), _objects2(_data[126]), _objects3(_data[127]), _objects4(_data[97]), _objects5(_data[98]), _objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]), - _objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]) { + _objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]), + _combatImgs1(&_data[162]), _combatImgs2(&_data[135]), + _combatImgs3(&_data[111]), _combatImgs4(&_data[80]) { // Setup draw structure positions _data[0] = DrawStruct(0, 8, 8); _data[1] = DrawStruct(1, 8, 25); @@ -631,9 +635,118 @@ void InterfaceMap::draw3d(bool updateFlag) { events.wait(2); } +/** + * Handles animation of monsters, wall items, and combat within the 3d + * view by cycling the appropriate frame numbers + */ void InterfaceMap::animate3d() { + Combat &combat = *_vm->_combat; + Map &map = *_vm->_map; + _overallFrame = (_overallFrame + 1) % 5; + _combatFloatCounter = (_combatFloatCounter + 1) % 8; + + for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) { + MazeMonster &monster = map._mobData._monsters[idx]; + if (!monster._field7) { + if (monster._frame < 8) { + MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + if (!monsterData._loopAnimation) { + // Monster isn't specially looped, so cycle through the 8 frames + monster._frame = (monster._frame + 1) % 8; + } else if (!monster._field9) { + monster._frame = (monster._frame + 1) % 8; + if (monster._frame == 0) { + monster._field9 ^= 1; + monster._frame = 6; + } + } else { + if (monster._frame) + --monster._frame; + if (monster._frame == 0) + monster._field9 = 0; + } + } else if (monster._frame == 11) { + --monster._fieldA; + if (monster._fieldA == 0) + monster._frame = 0; + } else { + ++monster._frame; + if (monster._frame == 11) { + --monster._frame; + monster._frame = monster._fieldA ? 10 : 0; + } + } + } + // Block 2 + if (monster._effect2) { + if (monster._effect1) { + if (monster._effect1 & 0x80) { + if (monster._effect3) + --monster._effect3; + if (monster._effect3 == 0) + monster._effect1 ^= 0x80; + } else { + monster._effect3 = (monster._effect3 + 1) % 3; + if (monster._effect3 == 0) { + monster._effect1 ^= 0x80; + monster._effect3 = 2; + } + } + } + } else { + monster._effect3 = (monster._effect3 + 1) % 8; + if (monster._effect3 == 0) { + MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + monster._effect1 = monster._effect2 = monsterData._animationEffect; + } + } + } + + DrawStruct *combatImgs1 = map._isOutdoors ? _outdoorList._combatImgs1 : _indoorList._combatImgs1; + DrawStruct *combatImgs2 = map._isOutdoors ? _outdoorList._combatImgs2 : _indoorList._combatImgs2; + DrawStruct *combatImgs3 = map._isOutdoors ? _outdoorList._combatImgs3 : _indoorList._combatImgs3; + DrawStruct *combatImgs4 = map._isOutdoors ? _outdoorList._combatImgs4 : _indoorList._combatImgs4; + + if (_flag1) { + for (int idx = 0; idx < 8; ++idx) { + if (combatImgs1[idx]._sprites) { + combatImgs1[idx]._sprites = nullptr; + combat._shooting[idx] = false; + } else if (combatImgs2[idx]._sprites) { + combatImgs1[idx]._sprites = combatImgs2[idx]._sprites; + combatImgs2[idx]._sprites = nullptr; + } else if (combatImgs3[idx]._sprites) { + combatImgs2[idx]._sprites = combatImgs3[idx]._sprites; + combatImgs3[idx]._sprites = nullptr; + } else if (combatImgs4[idx]._sprites) { + combatImgs3[idx]._sprites = combatImgs4[idx]._sprites; + combatImgs4[idx]._sprites = nullptr; + } + } + } else if (_charsShooting) { + for (int idx = 0; idx < 8; ++idx) { + if (combatImgs4[idx]._sprites) { + combatImgs4[idx]._sprites = nullptr; + } else if (combatImgs3[idx]._sprites) { + combatImgs4[idx]._sprites = combatImgs3[idx]._sprites; + combatImgs3[idx]._sprites = nullptr; + } else if (combatImgs2[idx]._sprites) { + combatImgs3[idx]._sprites = combatImgs2[idx]._sprites; + combatImgs2[idx]._sprites = nullptr; + } else if (combatImgs1[idx]._sprites) { + combatImgs2[idx]._sprites = combatImgs1[idx]._sprites; + combatImgs1[idx]._sprites = nullptr; + } + } + } + + for (uint idx = 0; idx < map._mobData._wallItems.size(); ++idx) { + MazeWallItem &wallItem = map._mobData._wallItems[idx]; + wallItem._frame = (wallItem._frame + 1) % wallItem._sprites->size(); + } } + void InterfaceMap::setMazeBits() { Common::fill(&_wo[0], &_wo[308], 0); diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 12e5ac6410..0867907516 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -36,6 +36,10 @@ public: DrawStruct _data[132]; DrawStruct &_skySprite; DrawStruct &_groundSprite; + DrawStruct * const _combatImgs1; + DrawStruct * const _combatImgs2; + DrawStruct * const _combatImgs3; + DrawStruct * const _combatImgs4; public: OutdoorDrawList(); @@ -68,6 +72,10 @@ public: DrawStruct &_objects0, &_objects1, &_objects2, &_objects3; DrawStruct &_objects4, &_objects5, &_objects6, &_objects7; DrawStruct &_objects8, &_objects9, &_objects10, &_objects11; + DrawStruct * const _combatImgs1; + DrawStruct * const _combatImgs2; + DrawStruct * const _combatImgs3; + DrawStruct * const _combatImgs4; public: IndoorDrawList(); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index d2f4c5e18d..5c49e37f4c 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -644,6 +644,9 @@ MazeMonster::MazeMonster() { _id = 0; _spriteId = 0; _isAttacking = false; + _field7 = 0; + _field9 = 0; + _fieldA = 0; _hp = 0; _effect1 = _effect2 = 0; _effect3 = 0; diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 8735973738..7815d143d5 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -236,6 +236,9 @@ struct MazeMonster { int _id; int _spriteId; bool _isAttacking; + int _field7; + int _field9; + int _fieldA; int _hp; int _effect1, _effect2; int _effect3; -- cgit v1.2.3 From 2b51d324f3cc2a58f2a703c23030ee19ba85836b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 22 Jan 2015 22:05:36 -0500 Subject: XEEN: Implemented dialogs for Who Will and YesNo --- engines/xeen/dialogs_error.h | 3 - engines/xeen/dialogs_whowill.cpp | 104 ++++++++++++++++++++++++++ engines/xeen/dialogs_whowill.h | 43 +++++++++++ engines/xeen/dialogs_yesno.cpp | 94 ++++++++++++++++++++++++ engines/xeen/dialogs_yesno.h | 43 +++++++++++ engines/xeen/interface.h | 1 + engines/xeen/interface_map.cpp | 13 +++- engines/xeen/interface_map.h | 6 +- engines/xeen/map.h | 2 + engines/xeen/module.mk | 2 + engines/xeen/party.cpp | 6 ++ engines/xeen/party.h | 2 + engines/xeen/resources.cpp | 14 ++++ engines/xeen/resources.h | 6 ++ engines/xeen/scripts.cpp | 154 ++++++++++++++++++++++++++------------- engines/xeen/scripts.h | 5 +- engines/xeen/xeen.cpp | 6 +- engines/xeen/xeen.h | 4 +- 18 files changed, 444 insertions(+), 64 deletions(-) create mode 100644 engines/xeen/dialogs_whowill.cpp create mode 100644 engines/xeen/dialogs_whowill.h create mode 100644 engines/xeen/dialogs_yesno.cpp create mode 100644 engines/xeen/dialogs_yesno.h (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_error.h b/engines/xeen/dialogs_error.h index 03a6f16cf2..ba36f285cf 100644 --- a/engines/xeen/dialogs_error.h +++ b/engines/xeen/dialogs_error.h @@ -23,9 +23,6 @@ #ifndef XEEN_DIALOGS_ERROR_H #define XEEN_DIALOGS_ERROR_H -#include "common/array.h" -#include "common/stack.h" -#include "common/rect.h" #include "xeen/dialogs.h" namespace Xeen { diff --git a/engines/xeen/dialogs_whowill.cpp b/engines/xeen/dialogs_whowill.cpp new file mode 100644 index 0000000000..402f5c6107 --- /dev/null +++ b/engines/xeen/dialogs_whowill.cpp @@ -0,0 +1,104 @@ +/* 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 "xeen/dialogs_whowill.h" +#include "xeen/resources.h" +#include "xeen/xeen.h" + +namespace Xeen { + +int WhoWill::show(XeenEngine *vm, int message, int action, bool type) { + WhoWill *dlg = new WhoWill(vm); + int result = dlg->execute(message, action, type); + delete dlg; + + return result; +} + +int WhoWill::execute(int message, int action, bool type) { + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + Scripts &scripts = *_vm->_scripts; + int numFrames; + + if (party._partyCount <= 1) + // Unless there's at least two characters, just return the first one + return 1; + + screen._windows[38].close(); + screen._windows[12].close(); + + Common::String actionStr = type ? map._events._text[action] : WHO_WILL_ACTIONS[action]; + Common::String msg = Common::String::format(WHO_WILL, actionStr.c_str(), + WHO_ACTIONS[message], party._partyCount); + + screen._windows[36].open(); + screen._windows[36].writeString(msg); + screen._windows[36].update(); + + intf._face1State = map._headData[party._mazePosition.y][party._mazePosition.x]._left; + intf._face2State = map._headData[party._mazePosition.y][party._mazePosition.x]._right; + + while (!_vm->shouldQuit()) { + events.updateGameCounter(); + + if (screen._windows[11]._enabled) { + intf.drawTownAnim(0); + screen._windows[36].frame(); + numFrames = 3; + } else { + intf.draw3d(false); + screen._windows[36].frame(); + screen._windows[3].update(); + numFrames = 1; + } + + events.wait(numFrames, true); + if (!_buttonValue) + continue; + + if (_buttonValue == 27) { + _buttonValue = 0; + break; + } else if (_buttonValue >= 201 && _buttonValue <= 206) { + _buttonValue -= 201; + if (_buttonValue > party._partyCount) + continue; + + if (party._activeParty[_buttonValue - 1].noActions()) + continue; + + scripts._whoWill = _buttonValue; + break; + } + } + + + intf._face1State = intf._face2State = 2; + screen._windows[36].close(); + return _buttonValue; +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_whowill.h b/engines/xeen/dialogs_whowill.h new file mode 100644 index 0000000000..8080c36ddb --- /dev/null +++ b/engines/xeen/dialogs_whowill.h @@ -0,0 +1,43 @@ +/* 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 XEEN_DIALOGS_WHOWHILL_H +#define XEEN_DIALOGS_WHOWHILL_H + +#include "xeen/dialogs.h" + +namespace Xeen { + +class WhoWill : public ButtonContainer { +private: + XeenEngine *_vm; + + WhoWill(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + int execute(int message, int action, bool type); +public: + static int show(XeenEngine *vm, int message, int action, bool type); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_WHOWHILL_H */ diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp new file mode 100644 index 0000000000..cefafa0feb --- /dev/null +++ b/engines/xeen/dialogs_yesno.cpp @@ -0,0 +1,94 @@ +/* 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 "xeen/dialogs_yesno.h" +#include "xeen/xeen.h" + +namespace Xeen { + +bool YesNo::show(XeenEngine *vm, bool type, int v2) { + YesNo *dlg = new YesNo(vm); + bool result = dlg->execute(type, v2); + delete dlg; + + return result; +} + +bool YesNo::execute(bool type, int v2) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + SpriteResource confirmSprites; + int numFrames; + bool result = false; + + Mode oldMode = _vm->_mode; + _vm->_mode = oldMode == MODE_7 ? MODE_8 : MODE_7; + + if (!type) { + confirmSprites.load("confirm.icn"); + intf._globalSprites.draw(screen, 7, Common::Point(232, 74)); + confirmSprites.draw(screen, 0, Common::Point(235, 75)); + confirmSprites.draw(screen, 2, Common::Point(260, 75)); + screen._windows[34].update(); + + addButton(Common::Rect(235, 75, 259, 95), 'Y', &confirmSprites); + addButton(Common::Rect(260, 75, 284, 95), 'N', &confirmSprites); + + intf._face1State = map._headData[party._mazePosition.y][party._mazePosition.x]._left; + intf._face2State = map._headData[party._mazePosition.y][party._mazePosition.x]._right; + } + + while (!_vm->shouldQuit()) { + events.updateGameCounter(); + + if (intf._townSprites[0].empty()) { + intf.draw3d(true); + numFrames = 1; + } else { + intf.drawTownAnim(v2); + numFrames = 3; + } + + events.wait(3, true); + if (!_buttonValue) + continue; + + if (type || _buttonValue == 'Y') { + result = true; + break; + } else if (_buttonValue == 'N' || _buttonValue == Common::KEYCODE_ESCAPE) + break; + } + + intf._face1State = intf._face2State = 2; + _vm->_mode = oldMode; + + if (!type) + intf.mainIconsPrint(); + + return result; +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_yesno.h b/engines/xeen/dialogs_yesno.h new file mode 100644 index 0000000000..82ac402c85 --- /dev/null +++ b/engines/xeen/dialogs_yesno.h @@ -0,0 +1,43 @@ +/* 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 XEEN_DIALOGS_YESNO_H +#define XEEN_DIALOGS_YESNO_H + +#include "xeen/dialogs.h" + +namespace Xeen { + +class YesNo : public ButtonContainer { +private: + XeenEngine *_vm; + + YesNo(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + bool execute(bool type, int v2); +public: + static bool show(XeenEngine *vm, bool type, int v2); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_YESNO_H */ diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 28f2bbee75..7879da59ed 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -76,6 +76,7 @@ private: bool checkMoveDirection(int key); public: + SpriteResource _townSprites[8]; int _intrIndex1; public: Interface(XeenEngine *vm); diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 70297be5af..2d2fddf4e0 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -393,6 +393,7 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) { _tillMove = 0; _flag1 = false; _overallFrame = 0; + _face1State = _face2State = 0; } void InterfaceMap::setup() { @@ -3852,15 +3853,15 @@ void InterfaceMap::assembleBorder() { // Handle the face UI elements for indicating clairvoyance status _face1UIFrame = (_face1UIFrame + 1) % 4; - if (_vm->_face1State == 0) + if (_face1State == 0) _face1UIFrame += 4; - else if (_vm->_face1State == 2) + else if (_face1State == 2) _face1UIFrame = 0; _face2UIFrame = (_face2UIFrame + 1) % 4 + 12; - if (_vm->_face2State == 0) + if (_face2State == 0) _face2UIFrame += 252; - else if (_vm->_face2State == 2) + else if (_face2State == 2) _face2UIFrame = 0; if (!_vm->_party->_clairvoyanceActive) { @@ -4310,4 +4311,8 @@ void InterfaceMap::drawMiniMap() { party._wizardEyeActive = eyeActive; } +void InterfaceMap::drawTownAnim(int v) { + warning("TODO"); +} + } // End of namespace Xeen diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 0867907516..51b82a9445 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -103,7 +103,6 @@ private: void setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, SpriteResource *sprites, int frame, int defaultY); protected: - SpriteResource _globalSprites; int8 _wp[20]; byte _wo[308]; bool _flipWater; @@ -143,8 +142,11 @@ protected: public: OutdoorDrawList _outdoorList; IndoorDrawList _indoorList; + SpriteResource _globalSprites; bool _upDoorText; Common::String _screenText; + int _face1State; + int _face2State; public: InterfaceMap(XeenEngine *vm); @@ -163,6 +165,8 @@ public: void setOutdoorsMonsters(); void setOutdoorsObjects(); + + void drawTownAnim(int v); }; } // End of namespace Xeen diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 7815d143d5..58e3aaa39c 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -309,6 +309,8 @@ public: HeadData(); void synchronize(Common::SeekableReadStream &s); + + HeadEntry *operator[](int y) { return &_data[y][0]; } }; struct AnimationFrame { int _front, _left, _back, _right; }; diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 6362ffe1bf..05a9b23797 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -10,6 +10,8 @@ MODULE_OBJS := \ dialogs.o \ dialogs_error.o \ dialogs_options.o \ + dialogs_whowill.o \ + dialogs_yesno.o \ events.o \ files.o \ font.o \ diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index d465cc9975..c1c4062172 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -167,6 +167,12 @@ bool PlayerStruct::charSavingThrow() { return false; } +bool PlayerStruct::noActions() { + // TODO + return false; +} + + /*------------------------------------------------------------------------*/ void Roster::synchronize(Common::Serializer &s) { diff --git a/engines/xeen/party.h b/engines/xeen/party.h index c598e8c3f9..19376839af 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -139,6 +139,8 @@ public: int getStat(int statNum, int v2); bool charSavingThrow(); + + bool noActions(); }; class Roster: public Common::Array<PlayerStruct> { diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 085f84aa73..994762bf5b 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -68,6 +68,9 @@ const char *const OPTIONS_TITLE = const char *const THE_PARTY_NEEDS_REST = "\x0B""012The Party needs rest!"; +const char *const WHO_WILL = "\X03""c\X0B""000\x09""000%s\x0A\x0A" + "Who will\x0A%s?\x0A\x0B""055F1 - F%d"; + const char *const TERRAIN_TYPES[6] = { "town", "cave", "towr", "cstl", "dung", "scfi" }; @@ -85,6 +88,17 @@ const char *const SURFACE_NAMES[16] = { "space.srf" }; +const char *const WHO_ACTIONS[32] = { + "aSearch", "aOpen", "aDrink", "aMine", "aTouch", "aRead", "aLearn", "aTake", + "aBang", "aSteal", "aBribe", "aPay", "aSit", "aTry", "aTurn", "aBathe", + "aDestroy", "aPull", "aDescend", "aTossACoin", "aPray", "aJoin", "aAct", + "aPlay", "aPush", "aRub", "aPick", "aEat", "aSign", "aClose", "aLook", "aTry" +}; + +const char *const WHO_WILL_ACTIONS[4] = { + "Open Grate", "Open Door", "Open Scroll", "Select Char" +}; + const byte SYMBOLS[20][64] = { { // 0 0x00, 0x00, 0xA8, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x00, 0xA8, 0x9E, 0x9C, 0x9C, 0x9E, 0x9E, 0x9E, diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index f6bcffaf4e..28a35543b6 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -34,12 +34,18 @@ extern const char *const OPTIONS_TITLE; extern const char *const THE_PARTY_NEEDS_REST; +extern const char *const WHO_WILL; + extern const char *const TERRAIN_TYPES[6]; extern const char *const SURFACE_TYPE_NAMES[15]; extern const char *const SURFACE_NAMES[16]; +extern const char *const WHO_ACTIONS[32]; + +extern const char *const WHO_WILL_ACTIONS[4]; + extern const byte SYMBOLS[20][64]; extern const byte TEXT_COLORS[40][4]; diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 73c0445011..4ccac8b1af 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -21,6 +21,7 @@ */ #include "xeen/scripts.h" +#include "xeen/dialogs_whowill.h" #include "xeen/party.h" #include "xeen/xeen.h" @@ -72,7 +73,8 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) { _treasureItems = 0; _treasureGold = 0; _treasureGems = 0; - + _lineNum = 0; + _charIndex = 0; _v2 = 0; _nEdamageType = 0; _animCounter = 0; @@ -85,7 +87,7 @@ void Scripts::checkEvents() { Map &map = *_vm->_map; Party &party = *_vm->_party; - int var18 = 0; +// int var18 = 0; _itemType = 0; _var4F = 0; bool var50 = false; @@ -102,14 +104,14 @@ void Scripts::checkEvents() { do { _lineNum = 0; - int varA = 0; +// int varA = 0; _animCounter = 0; - int var4E = 0; +// int var4E = 0; const Common::Point pt = party._mazePosition; - int varC = 1; + _charIndex = 1; _v2 = 1; _nEdamageType = 0; - int var40 = -1; +// int var40 = -1; while (_lineNum >= 0) { // Break out of the events if there's an attacking monster @@ -232,6 +234,9 @@ void Scripts::cmdDoorTextLrg(Common::Array<byte> ¶ms) { cmdNoAction(params); } +/** + * Show a sign text on-screen + */ void Scripts::cmdSignText(Common::Array<byte> ¶ms) { Interface &intf = *_vm->_interface; intf._screenText = Common::String::format("\f08\x03""c\t120\v088%s\x03""l\fd", @@ -247,6 +252,9 @@ void Scripts::cmdNPC(Common::Array<byte> ¶ms) { warning("TODO: cmdNPC"); } +/** + * Play a sound FX + */ void Scripts::cmdPlayFX(Common::Array<byte> ¶ms) { _vm->_sound->playFX(params[0]); @@ -255,74 +263,118 @@ void Scripts::cmdPlayFX(Common::Array<byte> ¶ms) { } void Scripts::cmdTeleport(Common::Array<byte> ¶ms) { + error("TODO"); } +/** + * Do a conditional check + */ void Scripts::cmdIf(Common::Array<byte> ¶ms) { switch (params[0]) { case 16: case 34: case 100: + // TODO break; case 25: case 35: case 101: case 106: + // TODO break; default: break; } } -void Scripts::cmdMoveObj(Common::Array<byte> ¶ms) {} -void Scripts::cmdTakeOrGive(Common::Array<byte> ¶ms) {} +void Scripts::cmdMoveObj(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdTakeOrGive(Common::Array<byte> ¶ms) { error("TODO"); } +/** + * Move to the next line of the script + */ void Scripts::cmdNoAction(Common::Array<byte> ¶ms) { // Move to next line _lineNum = _vm->_party->_partyDead ? -1 : _lineNum + 1; } -void Scripts::cmdRemove(Common::Array<byte> ¶ms) {} -void Scripts::cmdSetChar(Common::Array<byte> ¶ms) {} -void Scripts::cmdSpawn(Common::Array<byte> ¶ms) {} -void Scripts::cmdDoTownEvent(Common::Array<byte> ¶ms) {} -void Scripts::cmdExit(Common::Array<byte> ¶ms) {} -void Scripts::cmdAfterMap(Common::Array<byte> ¶ms) {} -void Scripts::cmdGiveExtended(Common::Array<byte> ¶ms) {} -void Scripts::cmdConfirmWord(Common::Array<byte> ¶ms) {} -void Scripts::cmdDamage(Common::Array<byte> ¶ms) {} -void Scripts::cmdJumpRnd(Common::Array<byte> ¶ms) {} -void Scripts::cmdAfterEvent(Common::Array<byte> ¶ms) {} -void Scripts::cmdCallEvent(Common::Array<byte> ¶ms) {} -void Scripts::cmdReturn(Common::Array<byte> ¶ms) {} -void Scripts::cmdSetVar(Common::Array<byte> ¶ms) {} -void Scripts::cmdCutsceneEndClouds(Common::Array<byte> ¶ms) {} -void Scripts::cmdWhoWill(Common::Array<byte> ¶ms) {} -void Scripts::cmdRndDamage(Common::Array<byte> ¶ms) {} -void Scripts::cmdMoveWallObj(Common::Array<byte> ¶ms) {} -void Scripts::cmdAlterCellFlag(Common::Array<byte> ¶ms) {} -void Scripts::cmdAlterHed(Common::Array<byte> ¶ms) {} -void Scripts::cmdDisplayStat(Common::Array<byte> ¶ms) {} -void Scripts::cmdSeatTextSml(Common::Array<byte> ¶ms) {} -void Scripts::cmdPlayEventVoc(Common::Array<byte> ¶ms) {} -void Scripts::cmdDisplayBottom(Common::Array<byte> ¶ms) {} -void Scripts::cmdIfMapFlag(Common::Array<byte> ¶ms) {} -void Scripts::cmdSelRndChar(Common::Array<byte> ¶ms) {} -void Scripts::cmdGiveEnchanted(Common::Array<byte> ¶ms) {} -void Scripts::cmdItemType(Common::Array<byte> ¶ms) {} -void Scripts::cmdMakeNothingHere(Common::Array<byte> ¶ms) {} -void Scripts::cmdNoAction2(Common::Array<byte> ¶ms) {} -void Scripts::cmdChooseNumeric(Common::Array<byte> ¶ms) {} -void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> ¶ms) {} -void Scripts::cmdDisplayLarge(Common::Array<byte> ¶ms) {} -void Scripts::cmdExchObj(Common::Array<byte> ¶ms) {} -void Scripts::cmdFallToMap(Common::Array<byte> ¶ms) {} -void Scripts::cmdDisplayMain(Common::Array<byte> ¶ms) {} -void Scripts::cmdGoto(Common::Array<byte> ¶ms) {} -void Scripts::cmdConfirmWord2(Common::Array<byte> ¶ms) {} -void Scripts::cmdGotoRandom(Common::Array<byte> ¶ms) {} -void Scripts::cmdCutsceneEndDarkside(Common::Array<byte> ¶ms) {} -void Scripts::cmdCutsceneEdWorld(Common::Array<byte> ¶ms) {} -void Scripts::cmdFlipWorld(Common::Array<byte> ¶ms) {} -void Scripts::cmdPlayCD(Common::Array<byte> ¶ms) {} +void Scripts::cmdRemove(Common::Array<byte> ¶ms) { error("TODO"); } + +/** + * Set the currently active character for other script operations + */ +void Scripts::cmdSetChar(Common::Array<byte> ¶ms) { + if (params[0] != 7) { + _charIndex = WhoWill::show(_vm, 22, 3, false); + if (_charIndex == 0) { + cmdExit(params); + return; + } + } else { + _charIndex = _vm->getRandomNumber(1, _vm->_party->_partyCount); + } + + _v2 = 1; + cmdNoAction(params); +} + +void Scripts::cmdSpawn(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdDoTownEvent(Common::Array<byte> ¶ms) { error("TODO"); } + +/** + * Stop executing the script + */ +void Scripts::cmdExit(Common::Array<byte> ¶ms) { + _lineNum = -1; +} + +void Scripts::cmdAfterMap(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdGiveExtended(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdConfirmWord(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdDamage(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdJumpRnd(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdAfterEvent(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdCallEvent(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdReturn(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdSetVar(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdCutsceneEndClouds(Common::Array<byte> ¶ms) { error("TODO"); } + +void Scripts::cmdWhoWill(Common::Array<byte> ¶ms) { + _charIndex = WhoWill::show(_vm, params[0], params[1], true); + + _var4F = true; + if (_charIndex == 0) + cmdExit(params); + else + cmdNoAction(params); +} + +void Scripts::cmdRndDamage(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdMoveWallObj(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdAlterCellFlag(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdAlterHed(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdDisplayStat(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdSeatTextSml(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdPlayEventVoc(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdDisplayBottom(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdIfMapFlag(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdSelRndChar(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdGiveEnchanted(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdItemType(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdMakeNothingHere(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdNoAction2(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdChooseNumeric(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdDisplayLarge(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdExchObj(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdFallToMap(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdDisplayMain(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdGoto(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdConfirmWord2(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdGotoRandom(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdCutsceneEndDarkside(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdCutsceneEdWorld(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdFlipWorld(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdPlayCD(Common::Array<byte> ¶ms) { error("TODO"); } } // End of namespace Xeen diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 808566af39..2e4996e6be 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -121,12 +121,12 @@ class Scripts { private: XeenEngine *_vm; int _charFX[6]; - int _whoWill; int _itemType; int _treasureItems; int _treasureGold; int _treasureGems; int _lineNum; + int _charIndex; int _v2; int _var4F; @@ -134,6 +134,8 @@ private: Common::String _paramText; MazeEvent *_event; + int whoWill(int v1, int v2, int v3); + void doOpcode(MazeEvent &event); void cmdDisplay1(Common::Array<byte> ¶ms); void cmdDoorTextSml(Common::Array<byte> ¶ms); @@ -192,6 +194,7 @@ private: public: int _animCounter; bool _eventSkipped; + int _whoWill; public: Scripts(XeenEngine *vm); diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 38026d0117..2d824e53bc 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -50,8 +50,6 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _eventData = nullptr; _loadDarkSide = 1; _dangerSenseAllowed = false; - _face1State = 0; - _face2State = 0; _noDirectionSense = false; _moveMonsters = false; _mode = MODE_0; @@ -128,6 +126,10 @@ int XeenEngine::getRandomNumber(int maxNumber) { return _randomSource.getRandomNumber(maxNumber); } +int XeenEngine::getRandomNumber(int minNumber, int maxNumber) { + return getRandomNumber(maxNumber - minNumber) + minNumber; +} + Common::Error XeenEngine::saveGameState(int slot, const Common::String &desc) { Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving( generateSaveName(slot)); diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 3e8637476a..cf872b3ede 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -145,8 +145,6 @@ public: Roster _roster; int _loadDarkSide; bool _dangerSenseAllowed; - int _face1State; - int _face2State; bool _noDirectionSense; bool _moveMonsters; int _openDoor; @@ -163,6 +161,8 @@ public: int getRandomNumber(int maxNumber); + int getRandomNumber(int minNumber, int maxNumber); + /** * Load a savegame */ -- cgit v1.2.3 From 749372e456ed8f1a4aee31ce23c4f4f7fd5644cc Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 23 Jan 2015 20:44:02 -0500 Subject: XEEN: More script code and string input dialog --- engines/xeen/dialogs_string_input.cpp | 75 +++++++++++++++ engines/xeen/dialogs_string_input.h | 45 +++++++++ engines/xeen/dialogs_whowill.cpp | 1 + engines/xeen/dialogs_yesno.cpp | 1 + engines/xeen/interface.cpp | 2 +- engines/xeen/interface.h | 2 +- engines/xeen/interface_map.h | 2 +- engines/xeen/items.cpp | 4 + engines/xeen/items.h | 13 +++ engines/xeen/map.cpp | 10 +- engines/xeen/map.h | 2 + engines/xeen/module.mk | 1 + engines/xeen/party.cpp | 40 +++++++- engines/xeen/party.h | 6 +- engines/xeen/resources.cpp | 4 +- engines/xeen/resources.h | 4 +- engines/xeen/saves.cpp | 4 + engines/xeen/saves.h | 2 + engines/xeen/screen.cpp | 78 ++++++++++++++++ engines/xeen/screen.h | 5 + engines/xeen/scripts.cpp | 170 ++++++++++++++++++++++++++++++++-- engines/xeen/scripts.h | 15 ++- engines/xeen/xeen.cpp | 1 + engines/xeen/xeen.h | 3 + 24 files changed, 467 insertions(+), 23 deletions(-) create mode 100644 engines/xeen/dialogs_string_input.cpp create mode 100644 engines/xeen/dialogs_string_input.h (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_string_input.cpp b/engines/xeen/dialogs_string_input.cpp new file mode 100644 index 0000000000..03191f877d --- /dev/null +++ b/engines/xeen/dialogs_string_input.cpp @@ -0,0 +1,75 @@ +/* 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 "xeen/dialogs_string_input.h" +#include "xeen/xeen.h" + +namespace Xeen { + +int StringInput::show(XeenEngine *vm, bool type, const Common::String &msg1, + const Common::String &msg2, int opcdoe) { + StringInput *dlg = new StringInput(vm); + int result = dlg->execute(type, msg1, msg2, opcdoe); + delete dlg; + + return result; +} + +int StringInput::execute(bool type, const Common::String &expected, + const Common::String &title, int opcode) { + Interface &intf = *_vm->_interface; + Screen &screen = *_vm->_screen; + Window &w = screen._windows[6]; + SoundManager &sound = *_vm->_sound; + int result = 0; + + w.open(); + w.writeString(Common::String::format("\r\x03""c%s\v024\t000", title.c_str())); + w.update(); + + Common::String line; + if (w.getString(line, 30, 200)) { + if (type) { + if (line == intf._interfaceText) { + result = true; + } else if (line == expected) { + result = (opcode == 55) ? -1 : 1; + } + } else { + // Load in the mirror list + File f(Common::String::format("%smirr.txt", + _vm->_files->_isDarkCc ? "dark" : "xeen")); + for (int idx = 0; f.pos() < f.size(); ++idx) { + if (line == f.readLine()) { + result = idx; + sound.playFX(_vm->_files->_isDarkCc ? 35 : 61); + break; + } + } + } + } + + w.close(); + return result; +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_string_input.h b/engines/xeen/dialogs_string_input.h new file mode 100644 index 0000000000..1e18726ff2 --- /dev/null +++ b/engines/xeen/dialogs_string_input.h @@ -0,0 +1,45 @@ +/* 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 XEEN_DIALOGS_STRING_INPUT_H +#define XEEN_DIALOGS_STRING_INPUT_H + +#include "xeen/dialogs.h" + +namespace Xeen { + +class StringInput : public ButtonContainer { +private: + XeenEngine *_vm; + + StringInput(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + int execute(bool type, const Common::String &expected, + const Common::String &title, int opcode); +public: + static int show(XeenEngine *vm, bool type, const Common::String &msg1, + const Common::String &msg2, int opcdoe); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_STRING_INPUT_H */ diff --git a/engines/xeen/dialogs_whowill.cpp b/engines/xeen/dialogs_whowill.cpp index 402f5c6107..042214a3dc 100644 --- a/engines/xeen/dialogs_whowill.cpp +++ b/engines/xeen/dialogs_whowill.cpp @@ -76,6 +76,7 @@ int WhoWill::execute(int message, int action, bool type) { } events.wait(numFrames, true); + checkEvents(_vm); if (!_buttonValue) continue; diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp index cefafa0feb..6f74d86ca4 100644 --- a/engines/xeen/dialogs_yesno.cpp +++ b/engines/xeen/dialogs_yesno.cpp @@ -72,6 +72,7 @@ bool YesNo::execute(bool type, int v2) { } events.wait(3, true); + checkEvents(_vm); if (!_buttonValue) continue; diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 31fe00b0b8..7487d63788 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -485,7 +485,7 @@ void Interface::perform() { if (_buttonValue == Common::KEYCODE_SPACE || (events._leftButton && waitBounds.contains(events._mousePos))) { int lookupId = map.mazeLookup(party._mazePosition, - WALL_NUMBERS[party._mazeDirection][2]); + WALL_SHIFTS[party._mazeDirection][2]); bool eventsFlag = true; switch (lookupId) { diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 7879da59ed..3d8116d03d 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -52,7 +52,6 @@ private: bool _buttonsLoaded; int _hiliteChar; int _steppingFX; - Common::String _interfaceText; void initDrawStructs(); @@ -78,6 +77,7 @@ private: public: SpriteResource _townSprites[8]; int _intrIndex1; + Common::String _interfaceText; public: Interface(XeenEngine *vm); diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 51b82a9445..914120fb2c 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -124,7 +124,6 @@ protected: int _holyBonusUIFrame; int _heroismUIFrame; int _flipUIFrame; - byte _tillMove; bool _flag1; int _overallFrame; @@ -147,6 +146,7 @@ public: Common::String _screenText; int _face1State; int _face2State; + byte _tillMove; public: InterfaceMap(XeenEngine *vm); diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp index e22e8656d7..e9425f7ee9 100644 --- a/engines/xeen/items.cpp +++ b/engines/xeen/items.cpp @@ -36,4 +36,8 @@ void XeenItem::synchronize(Common::Serializer &s) { s.syncAsByte(_equipped); } +Treasure::Treasure() { + _hasItems = false; +} + } // End of namespace Xeen diff --git a/engines/xeen/items.h b/engines/xeen/items.h index eba2354da5..6fa57b922a 100644 --- a/engines/xeen/items.h +++ b/engines/xeen/items.h @@ -28,6 +28,8 @@ namespace Xeen { +#define TOTAL_ITEMS 10 + class XeenItem { public: int _material; @@ -40,6 +42,17 @@ public: void synchronize(Common::Serializer &s); }; +class Treasure { +public: + XeenItem _misc[TOTAL_ITEMS]; + XeenItem _accessories[TOTAL_ITEMS]; + XeenItem _armor[TOTAL_ITEMS]; + XeenItem _weapons[TOTAL_ITEMS]; + bool _hasItems; +public: + Treasure(); +}; + } // End of namespace Xeen #endif /* XEEN_ITEMS_H */ diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 5c49e37f4c..7801a050bb 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1367,6 +1367,14 @@ void Map::setCellSurfaceFlags(const Common::Point &pt, int bits) { _mazeData[0]._cells[pt.y][pt.x]._surfaceId |= bits; } +void Map::setWall(const Common::Point &pt, Direction dir, int v) { + const int XOR_MASKS[4] = { 0xFFF, 0xF0FF, 0xFF0F, 0xFFF0 }; + mazeLookup(pt, 0, 0); + + MazeWallLayers &wallLayer = _mazeData[0]._wallData[pt.y][pt.x]; + wallLayer._data &= XOR_MASKS[dir]; + wallLayer._data |= v << WALL_SHIFTS[dir][2]; +} int Map::getCell(int idx) { int mapId = _vm->_party->_mazeId; @@ -1489,7 +1497,7 @@ int Map::getCell(int idx) { _currentSurfaceId = _mazeData[_mazeDataIndex]._cells[pt.y][pt.x]._surfaceId; _currentWall = wallLayers; - return (_currentWall._data >> WALL_NUMBERS[dir][idx]) & 0xF; + return (_currentWall._data >> WALL_SHIFTS[dir][idx]) & 0xF; } return _currentWall._data; diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 58e3aaa39c..51f426d566 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -385,6 +385,8 @@ public: void setCellSurfaceFlags(const Common::Point &pt, int bits); + void setWall(const Common::Point &pt, Direction dir, int v); + void saveMaze(); int getCell(int idx); diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 05a9b23797..ea6ea8c073 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -10,6 +10,7 @@ MODULE_OBJS := \ dialogs.o \ dialogs_error.o \ dialogs_options.o \ + dialogs_string_input.o \ dialogs_whowill.o \ dialogs_yesno.o \ events.o \ diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index c1c4062172..b33318fcdf 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -51,7 +51,7 @@ PlayerStruct::PlayerStruct() { _dbDay = 0; _tempAge = 0; Common::fill(&_skills[0], &_skills[18], 0); - Common::fill(&_awards[0], &_awards[512], false); + Common::fill(&_awards[0], &_awards[128], false); Common::fill(&_spells[9], &_spells[312], false); _lloydMap = 0; _hasSpells = false; @@ -95,9 +95,21 @@ void PlayerStruct::synchronize(Common::Serializer &s) { s.syncAsByte(_dbDay); s.syncAsByte(_tempAge); - for (int i = 0; i < 18; ++i) - s.syncAsByte(_skills[i]); - SavesManager::syncBitFlags(s, &_awards[0], &_awards[512]); + // Synchronize the skill list + for (int idx = 0; idx < 18; ++idx) + s.syncAsByte(_skills[idx]); + + // Synchronize character awards + for (int idx = 0; idx < 64; ++idx) { + byte b = (_awards[idx] ? 1 : 0) | (_awards[idx + 64] ? 0x10 : 0); + s.syncAsByte(b); + if (s.isLoading()) { + _awards[idx] = (b & 0xF) != 0; + _awards[idx + 64] = (b & 0xF0) != 0; + } + } + + // Synchronize spell list SavesManager::syncBitFlags(s, &_spells[0], &_spells[312]); s.syncAsByte(_lloydMap); @@ -172,6 +184,26 @@ bool PlayerStruct::noActions() { return false; } +void PlayerStruct::setAward(int awardId, bool value) { + int v = awardId; + if (awardId == 73) + v = 126; + else if (awardId == 81) + v = 127; + + _awards[v] = value; +} + +bool PlayerStruct::hasAward(int awardId) { + int v = awardId; + if (awardId == 73) + v = 126; + else if (awardId == 81) + v = 127; + + return _awards[v]; +} + /*------------------------------------------------------------------------*/ diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 19376839af..a00b18910d 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -99,7 +99,7 @@ public: int _dbDay; int _tempAge; int _skills[18]; - bool _awards[512]; + bool _awards[128]; bool _spells[312]; int _lloydMap; Common::Point _lloydPosition; @@ -141,6 +141,10 @@ public: bool charSavingThrow(); bool noActions(); + + bool hasAward(int awardId); + + void setAward(int awardId, bool value); }; class Roster: public Common::Array<PlayerStruct> { diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 994762bf5b..c167bdbb48 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -71,6 +71,8 @@ const char *const THE_PARTY_NEEDS_REST = "\x0B""012The Party needs rest!"; const char *const WHO_WILL = "\X03""c\X0B""000\x09""000%s\x0A\x0A" "Who will\x0A%s?\x0A\x0B""055F1 - F%d"; +const char *const WHATS_THE_PASSWORD = "What's the Password?"; + const char *const TERRAIN_TYPES[6] = { "town", "cave", "towr", "cstl", "dung", "scfi" }; @@ -408,7 +410,7 @@ const int DIRECTION_ANIM_POSITIONS[4][4] = { { 0, 1, 2, 3 }, { 3, 0, 1, 2 }, { 2, 3, 0, 1 }, { 1, 2, 3, 0 } }; -const byte WALL_NUMBERS[4][48] = { +const byte WALL_SHIFTS[4][48] = { { 12, 0, 12, 8, 12, 12, 0, 12, 8, 12, 12, 0, 12, 0, 12, 8, 12, 8, 12, 12, 0, 12, 0, 12, diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 28a35543b6..e62454eafd 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -36,6 +36,8 @@ extern const char *const THE_PARTY_NEEDS_REST; extern const char *const WHO_WILL; +extern const char *const WHATS_THE_PASSWORD; + extern const char *const TERRAIN_TYPES[6]; extern const char *const SURFACE_TYPE_NAMES[15]; @@ -96,7 +98,7 @@ extern const int OUTDOOR_OBJECT_Y[2][12]; extern const int DIRECTION_ANIM_POSITIONS[4][4]; -extern const byte WALL_NUMBERS[4][48]; +extern const byte WALL_SHIFTS[4][48]; extern const int DRAW_NUMBERS[25]; diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index c2b15106eb..da791cdd77 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -168,4 +168,8 @@ void SavesManager::writeCharFile() { warning("TODO: writeCharFile"); } +void SavesManager::saveChars() { + warning("TODO: saveChars"); +} + } // End of namespace Xeen diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h index 6b73625c61..7dea941f8d 100644 --- a/engines/xeen/saves.h +++ b/engines/xeen/saves.h @@ -77,6 +77,8 @@ public: void writeCharFile(); + void saveChars(); + // Archive implementation virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; }; diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index de591d396d..42182cc7fe 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -182,6 +182,84 @@ void Window::drawList(DrawStruct *items, int count) { } } +/** + * Allows the user to enter a string + */ +int Window::getString(Common::String &line, int maxLen, int maxWidth) { + Interface &intf = *_vm->_interface; + + _vm->_noDirectionSense = true; + Common::String msg = Common::String::format("\x03""l\t000\x04%03d\x03""c", maxWidth); + writeString(msg); + update(); + + while (!_vm->shouldQuit()) { + Common::KeyCode keyCode = doCursor(msg); + + if ((keyCode == Common::KEYCODE_BACKSPACE || keyCode == Common::KEYCODE_DELETE) + && line.size() > 0) + line.deleteLastChar(); + else if (keyCode >= Common::KEYCODE_SPACE && keyCode < Common::KEYCODE_DELETE + && line.size() < maxLen && (line.size() > 0 || keyCode != Common::KEYCODE_SPACE)) { + + } else if (keyCode == Common::KEYCODE_RETURN || keyCode == Common::KEYCODE_KP_ENTER) { + break; + } else if (keyCode == Common::KEYCODE_ESCAPE) { + line = ""; + break; + } + } + + _vm->_noDirectionSense = false; + return line.size(); +} + +/** + * Draws the cursor and waits until the user presses a key + */ +Common::KeyCode Window::doCursor(const Common::String &msg) { + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Screen &screen = *_vm->_screen; + + bool oldUpDoorText = intf._upDoorText; + byte oldTillMove = intf._tillMove; + intf._upDoorText = false; + intf._tillMove = 0; + + bool flag = !_vm->_startupWindowActive && !screen._windows[25]._enabled + && _vm->_mode != MODE_FF && _vm->_mode != MODE_17; + + Common::KeyCode ch = Common::KEYCODE_INVALID; + while (!_vm->shouldQuit()) { + events.updateGameCounter(); + + if (flag) + intf.draw3d(false); + writeString(msg); + update(); + + if (flag) + screen._windows[3].update(); + + events.wait(1, true); + if (events.isKeyPending()) { + Common::KeyState keyState; + events.getKey(keyState); + ch = keyState.keycode; + break; + } + } + + writeString(""); + update(); + + intf._tillMove = oldTillMove; + intf._upDoorText = oldUpDoorText; + + return ch; +} + /*------------------------------------------------------------------------*/ /** diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index adf956e9bc..5e4e46ca21 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/system.h" #include "common/array.h" +#include "common/keyboard.h" #include "common/rect.h" #include "xeen/font.h" #include "xeen/sprites.h" @@ -66,6 +67,8 @@ private: int _ycL, _ycH; void open2(); + + Common::KeyCode doCursor(const Common::String &msg); public: bool _enabled; public: @@ -91,6 +94,8 @@ public: void writeString(const Common::String &s); void drawList(DrawStruct *items, int count); + + int getString(Common::String &line, int maxLen, int maxWidth); }; class Screen: public FontSurface { diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 4ccac8b1af..afc86ab433 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -21,8 +21,10 @@ */ #include "xeen/scripts.h" +#include "xeen/dialogs_string_input.h" #include "xeen/dialogs_whowill.h" #include "xeen/party.h" +#include "xeen/resources.h" #include "xeen/xeen.h" namespace Xeen { @@ -167,7 +169,7 @@ void Scripts::doOpcode(MazeEvent &event) { &Scripts::cmdIf, &Scripts::cmdIf, &Scripts::cmdIf, &Scripts::cmdMoveObj, &Scripts::cmdTakeOrGive, &Scripts::cmdNoAction, &Scripts::cmdRemove, &Scripts::cmdSetChar, &Scripts::cmdSpawn, - &Scripts::cmdDoTownEvent, &Scripts::cmdExit, &Scripts::cmdAfterMap, + &Scripts::cmdDoTownEvent, &Scripts::cmdExit, &Scripts::cmdAlterMap, &Scripts::cmdGiveExtended, &Scripts::cmdConfirmWord, &Scripts::cmdDamage, &Scripts::cmdJumpRnd, &Scripts::cmdAfterEvent, &Scripts::cmdCallEvent, &Scripts::cmdReturn, &Scripts::cmdSetVar, &Scripts::cmdTakeOrGive, @@ -180,7 +182,7 @@ void Scripts::doOpcode(MazeEvent &event) { &Scripts::cmdItemType, &Scripts::cmdMakeNothingHere, &Scripts::cmdNoAction2, &Scripts::cmdChooseNumeric, &Scripts::cmdDisplayBottomTwoLines, &Scripts::cmdDisplayLarge, &Scripts::cmdExchObj, &Scripts::cmdFallToMap, - &Scripts::cmdDisplayMain, &Scripts::cmdGoto, &Scripts::cmdConfirmWord2, + &Scripts::cmdDisplayMain, &Scripts::cmdGoto, &Scripts::cmdConfirmWord, &Scripts::cmdGotoRandom, &Scripts::cmdCutsceneEndDarkside, &Scripts::cmdCutsceneEdWorld, &Scripts::cmdFlipWorld, &Scripts::cmdPlayCD }; @@ -287,7 +289,21 @@ void Scripts::cmdIf(Common::Array<byte> ¶ms) { } } -void Scripts::cmdMoveObj(Common::Array<byte> ¶ms) { error("TODO"); } +/** + * Moves the position of an object + */ +void Scripts::cmdMoveObj(Common::Array<byte> ¶ms) { + MazeObject &mazeObj = _vm->_map->_mobData._objects[params[0]]; + + if (mazeObj._position.x == params[1] && mazeObj._position.y == params[2]) { + // Already in position, so simply flip it + mazeObj._flipped = !mazeObj._flipped; + } else { + mazeObj._position.x = params[1]; + mazeObj._position.y = params[2]; + } +} + void Scripts::cmdTakeOrGive(Common::Array<byte> ¶ms) { error("TODO"); } /** @@ -318,7 +334,23 @@ void Scripts::cmdSetChar(Common::Array<byte> ¶ms) { cmdNoAction(params); } -void Scripts::cmdSpawn(Common::Array<byte> ¶ms) { error("TODO"); } +/** + * Spawn a monster + */ +void Scripts::cmdSpawn(Common::Array<byte> ¶ms) { + MazeMonster &monster = _vm->_map->_mobData._monsters[params[0]]; + MonsterStruct &monsterData = _vm->_map->_monsterData[monster._spriteId]; + monster._position.x = params[1]; + monster._position.y = params[2]; + monster._frame = _vm->getRandomNumber(7); + monster._field7 = 0; + monster._isAttacking = params[1] != 0; + monster._hp = monsterData._hp; + + _var4F = 1; + cmdNoAction(params); +} + void Scripts::cmdDoTownEvent(Common::Array<byte> ¶ms) { error("TODO"); } /** @@ -328,9 +360,97 @@ void Scripts::cmdExit(Common::Array<byte> ¶ms) { _lineNum = -1; } -void Scripts::cmdAfterMap(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdGiveExtended(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdConfirmWord(Common::Array<byte> ¶ms) { error("TODO"); } +/** + * Changes the value for the wall on a given cell + */ +void Scripts::cmdAlterMap(Common::Array<byte> ¶ms) { + Map &map = *_vm->_map; + + if (params[2] == DIR_ALL) { + for (int dir = DIR_NORTH; dir <= DIR_WEST; ++dir) + map.setWall(Common::Point(params[0], params[1]), (Direction)dir, params[3]); + } else { + map.setWall(Common::Point(params[0], params[1]), (Direction)params[2], params[3]); + } + + _var4F = true; + cmdNoAction(params); +} + +void Scripts::cmdGiveExtended(Common::Array<byte> ¶ms) { + switch (params[0]) { + case 16: + case 34: + case 100: + // TODO + break; + case 25: + case 35: + case 101: + case 106: + // TODO + break; + default: + break; + } +} + +void Scripts::cmdConfirmWord(Common::Array<byte> ¶ms) { + Map &map = *_vm->_map; + Common::String msg1 = params[2] ? map._events._text[params[2]] : + _vm->_interface->_interfaceText; + Common::String msg2; + + if (_event->_opcode == OP_ConfirmWord_2) { + msg2 = map._events._text[params[3]]; + } else if (params[3]) { + msg2 = ""; + } else { + msg2 = WHATS_THE_PASSWORD; + } + + int result = StringInput::show(_vm, params[0], msg1, msg2,_event->_opcode); + if (result) { + if (result == 33 && _vm->_files->_isDarkCc) { + doEndGame2(); + } else if (result == 34 && _vm->_files->_isDarkCc) { + doWorldEnd(); + } else if (result == 35 && _vm->_files->_isDarkCc && + _vm->getGameID() == GType_WorldOfXeen) { + doEndGame(); + } else if (result == 40 && !_vm->_files->_isDarkCc) { + doEndGame(); + } else if (result == 60 && !_vm->_files->_isDarkCc) { + doEndGame2(); + } + else if (result == 61 && !_vm->_files->_isDarkCc) { + doWorldEnd(); + } else { + if (result == 59 && !_vm->_files->_isDarkCc) { + for (int idx = 0; idx < TOTAL_ITEMS; ++idx) { + XeenItem &item = _vm->_treasure._weapons[idx]; + if (!item._name) { + item._name = 34; + item._material = 0; + item._bonusFlags = 0; + _vm->_treasure._hasItems = true; + + cmdExit(params); + return; + } + } + } + + _lineNum = result == -1 ? params[3] : params[1]; + + return; + } + } + + _var4F = true; + cmdNoAction(params); +} + void Scripts::cmdDamage(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdJumpRnd(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdAfterEvent(Common::Array<byte> ¶ms) { error("TODO"); } @@ -370,11 +490,45 @@ void Scripts::cmdExchObj(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdFallToMap(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdDisplayMain(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdGoto(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdConfirmWord2(Common::Array<byte> ¶ms) { error("TODO"); } + void Scripts::cmdGotoRandom(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdCutsceneEndDarkside(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdCutsceneEdWorld(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdFlipWorld(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdPlayCD(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::doEndGame() { + doEnding("ENDGAME", 0); +} + +void Scripts::doEndGame2() { + Party &party = *_vm->_party; + int v2 = 0; + + for (int idx = 0; idx < party._partyCount; ++idx) { + PlayerStruct &player = party._activeParty[idx]; + if (player.hasAward(77)) { + v2 = 2; + break; + } + else if (player.hasAward(76)) { + v2 = 1; + break; + } + } + + doEnding("ENDGAME2", v2); +} + +void Scripts::doWorldEnd() { + +} + +void Scripts::doEnding(const Common::String &endStr, int v2) { + _vm->_saves->saveChars(); + + warning("TODO: doEnding"); +} + + } // End of namespace Xeen diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 2e4996e6be..5f931c1fb5 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -134,8 +134,6 @@ private: Common::String _paramText; MazeEvent *_event; - int whoWill(int v1, int v2, int v3); - void doOpcode(MazeEvent &event); void cmdDisplay1(Common::Array<byte> ¶ms); void cmdDoorTextSml(Common::Array<byte> ¶ms); @@ -153,7 +151,7 @@ private: void cmdSpawn(Common::Array<byte> ¶ms); void cmdDoTownEvent(Common::Array<byte> ¶ms); void cmdExit(Common::Array<byte> ¶ms); - void cmdAfterMap(Common::Array<byte> ¶ms); + void cmdAlterMap(Common::Array<byte> ¶ms); void cmdGiveExtended(Common::Array<byte> ¶ms); void cmdConfirmWord(Common::Array<byte> ¶ms); void cmdDamage(Common::Array<byte> ¶ms); @@ -185,12 +183,21 @@ private: void cmdFallToMap(Common::Array<byte> ¶ms); void cmdDisplayMain(Common::Array<byte> ¶ms); void cmdGoto(Common::Array<byte> ¶ms); - void cmdConfirmWord2(Common::Array<byte> ¶ms); void cmdGotoRandom(Common::Array<byte> ¶ms); void cmdCutsceneEndDarkside(Common::Array<byte> ¶ms); void cmdCutsceneEdWorld(Common::Array<byte> ¶ms); void cmdFlipWorld(Common::Array<byte> ¶ms); void cmdPlayCD(Common::Array<byte> ¶ms); + + int whoWill(int v1, int v2, int v3); + + void doEndGame(); + + void doEndGame2(); + + void doWorldEnd(); + + void doEnding(const Common::String &endStr, int v2); public: int _animCounter; bool _eventSkipped; diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 2d824e53bc..99adbb3a41 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -54,6 +54,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _moveMonsters = false; _mode = MODE_0; _openDoor = 0; + _startupWindowActive = false; } XeenEngine::~XeenEngine() { diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index cf872b3ede..1065adf9db 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -72,6 +72,7 @@ enum XeenDebugChannels { }; enum Mode { + MODE_FF = -1, MODE_0 = 0, MODE_1 = 1, MODE_2 = 2, @@ -139,6 +140,7 @@ public: Screen *_screen; Scripts *_scripts; SoundManager *_sound; + Treasure _treasure; Mode _mode; GameEvent _gameEvent; Common::SeekableReadStream *_eventData; @@ -148,6 +150,7 @@ public: bool _noDirectionSense; bool _moveMonsters; int _openDoor; + bool _startupWindowActive; public: XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); virtual ~XeenEngine(); -- cgit v1.2.3 From c08e54fde105637082ee7eb79eeacd1cb4137d57 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 23 Jan 2015 21:12:35 -0500 Subject: XEEN: Implement further script opcodes --- engines/xeen/interface.cpp | 5 +-- engines/xeen/map.cpp | 9 ++--- engines/xeen/map.h | 3 +- engines/xeen/party.cpp | 2 ++ engines/xeen/party.h | 3 ++ engines/xeen/saves.cpp | 2 ++ engines/xeen/saves.h | 3 ++ engines/xeen/scripts.cpp | 85 +++++++++++++++++++++++++++++++++++++++++----- engines/xeen/xeen.cpp | 5 ++- engines/xeen/xeen.h | 1 - 10 files changed, 98 insertions(+), 20 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 7487d63788..307027bacc 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -79,8 +79,9 @@ void Interface::setup() { } void Interface::manageCharacters(bool soundPlayed) { - Screen &screen = *_vm->_screen; EventsManager &events = *_vm->_events; + Map &map = *_vm->_map; + Screen &screen = *_vm->_screen; bool flag = false; start: @@ -106,7 +107,7 @@ start: // Build up a list of characters on the same Xeen side being loaded for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { PlayerStruct &player = _vm->_roster[i]; - if (player._name.empty() || player._xeenSide != _vm->_loadDarkSide) + if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0)) continue; xeenSideChars.push_back(i); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 7801a050bb..ca22b38d93 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -857,7 +857,8 @@ void AnimationInfo::load(const Common::String &name) { /*------------------------------------------------------------------------*/ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { - _townPortalSide = 0; + _townPortalSide = false; + _loadDarkSide = false; _sideObjects = 0; _sideMonsters = 0; _sidePictures = 0; @@ -896,13 +897,13 @@ void Map::load(int mapId) { _sideMonsters = 1; _sidePictures = 1; if (mapId >= 113 && mapId <= 127) { - _townPortalSide = 0; + _townPortalSide = false; } else { - _townPortalSide = _vm->_loadDarkSide; + _townPortalSide = _loadDarkSide; } if (_vm->getGameID() == GType_WorldOfXeen) { - if (_vm->_loadDarkSide) { + if (_loadDarkSide) { _animationInfo.load("clouds.dat"); _monsterData.load("xeen.mon"); _wallPicSprites.load("xeenpic.dat"); diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 51f426d566..273a4b4a9d 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -345,7 +345,7 @@ private: MazeData _mazeData[9]; Common::String _mazeName; SpriteResource _wallPicSprites; - int _townPortalSide; + bool _townPortalSide; int _sidePictures; int _sideObjects; int _sideMonsters; @@ -374,6 +374,7 @@ public: int _currentTile; int _currentSurfaceId; bool _currentSteppedOn; + bool _loadDarkSide; public: Map(XeenEngine *vm); diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index b33318fcdf..8d59e686fd 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -272,6 +272,8 @@ Party::Party(XeenEngine *vm): _vm(vm) { _stepped = false; _damageType = DT_PHYSICAL; _falling = false; + _fallMaze = 0; + _fallDamage = 0; } void Party::synchronize(Common::Serializer &s) { diff --git a/engines/xeen/party.h b/engines/xeen/party.h index a00b18910d..3962ba45c0 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -221,6 +221,9 @@ public: bool _isNight; bool _stepped; int _falling; + Common::Point _fallPosition; + int _fallMaze; + int _fallDamage; DamageType _damageType; public: Party(XeenEngine *vm); diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index da791cdd77..85ab60bc12 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -49,6 +49,8 @@ SavesManager::SavesManager(XeenEngine *vm, Party &party, Roster &roster) : BaseCCArchive(), _vm(vm), _party(party), _roster(roster) { SearchMan.add("saves", this, 0, false); _data = nullptr; + _wonWorld = false; + _wonDarkSide = false; } SavesManager::~SavesManager() { diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h index 7dea941f8d..5d35518348 100644 --- a/engines/xeen/saves.h +++ b/engines/xeen/saves.h @@ -66,6 +66,9 @@ private: void load(Common::SeekableReadStream *stream); public: static void syncBitFlags(Common::Serializer &s, bool *startP, bool *endP); +public: + bool _wonWorld; + bool _wonDarkSide; public: SavesManager(XeenEngine *vm, Party &party, Roster &roster); diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index afc86ab433..bbba4b9630 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -486,15 +486,82 @@ void Scripts::cmdNoAction2(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdChooseNumeric(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdDisplayLarge(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdExchObj(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdFallToMap(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdDisplayMain(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdGoto(Common::Array<byte> ¶ms) { error("TODO"); } - -void Scripts::cmdGotoRandom(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdCutsceneEndDarkside(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdCutsceneEdWorld(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdFlipWorld(Common::Array<byte> ¶ms) { error("TODO"); } + +/** + * Exchange the positions of two objects in the maze + */ +void Scripts::cmdExchObj(Common::Array<byte> ¶ms) { + MazeObject &obj1 = _vm->_map->_mobData._objects[params[0]]; + MazeObject &obj2 = _vm->_map->_mobData._objects[params[1]]; + + Common::Point pt = obj1._position; + obj1._position = obj2._position; + obj2._position = pt; + + _var4F = true; + cmdNoAction(params); +} + +void Scripts::cmdFallToMap(Common::Array<byte> ¶ms) { + Party &party = *_vm->_party; + party._fallMaze = params[0]; + party._fallPosition = Common::Point(params[1], params[2]); + party._fallDamage = params[3]; + + _var4F = true; + _lineNum = -1; +} + +void Scripts::cmdDisplayMain(Common::Array<byte> ¶ms) { + error("TODO"); +} + +/** + * Jumps to a given line number if the surface at relative cell position 1 matches + * a specified surface. + * @remarks This opcode is apparently never actually used + */ +void Scripts::cmdGoto(Common::Array<byte> ¶ms) { + Map &map = *_vm->_map; + map.getCell(1); + if (params[0] == map._currentSurfaceId) + _lineNum = params[1] - 1; + + _var4F = true; + cmdNoAction(params); +} + +/** + * Pick a random value from the parameter list and jump to that line number + */ +void Scripts::cmdGotoRandom(Common::Array<byte> ¶ms) { + _lineNum = params[_vm->getRandomNumber(1, params[0])] - 1; + _var4F = true; + cmdNoAction(params); +} + +void Scripts::cmdCutsceneEndDarkside(Common::Array<byte> ¶ms) { + Party &party = *_vm->_party; + _vm->_saves->_wonDarkSide = true; + party._questItems[53] = 1; + party._darkSideEnd = true; + party._mazeId = 29; + party._mazeDirection = DIR_NORTH; + party._mazePosition = Common::Point(25, 21); + + doEndGame2(); +} + +void Scripts::cmdCutsceneEdWorld(Common::Array<byte> ¶ms) { + _vm->_saves->_wonWorld = true; + _vm->_party->_worldEnd = true; + doWorldEnd(); +} + +void Scripts::cmdFlipWorld(Common::Array<byte> ¶ms) { + _vm->_map->_loadDarkSide = params[0] != 0; +} + void Scripts::cmdPlayCD(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::doEndGame() { diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 99adbb3a41..8489f86ed5 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -48,7 +48,6 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _scripts = nullptr; _sound = nullptr; _eventData = nullptr; - _loadDarkSide = 1; _dangerSenseAllowed = false; _noDirectionSense = false; _moveMonsters = false; @@ -287,8 +286,8 @@ void XeenEngine::play() { _screen->loadPalette("mm4.pal"); _interface->loadPartyIcons(); - if (getGameID() != GType_WorldOfXeen && !_loadDarkSide) { - _loadDarkSide = true; + if (getGameID() != GType_WorldOfXeen && !_map->_loadDarkSide) { + _map->_loadDarkSide = true; _party->_mazeId = 29; _party->_mazeDirection = DIR_NORTH; _party->_mazePosition.x = 25; diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 1065adf9db..b60908ddfe 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -145,7 +145,6 @@ public: GameEvent _gameEvent; Common::SeekableReadStream *_eventData; Roster _roster; - int _loadDarkSide; bool _dangerSenseAllowed; bool _noDirectionSense; bool _moveMonsters; -- cgit v1.2.3 From fac1d0642fe21600c775be6379c5fd4098ab9d4e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 23 Jan 2015 21:25:58 -0500 Subject: XEEN: Implement script opcodes for cmdCallEvent and cmdReturn --- engines/xeen/scripts.cpp | 35 ++++++++++++++++++++++++++++++----- engines/xeen/scripts.h | 9 +++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index bbba4b9630..247165f085 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -109,7 +109,7 @@ void Scripts::checkEvents() { // int varA = 0; _animCounter = 0; // int var4E = 0; - const Common::Point pt = party._mazePosition; + _currentPos = party._mazePosition; _charIndex = 1; _v2 = 1; _nEdamageType = 0; @@ -127,8 +127,8 @@ void Scripts::checkEvents() { for (eventIndex = 0; eventIndex < map._events.size(); ++eventIndex) { MazeEvent &event = map._events[eventIndex]; - if (event._position == pt && party._mazeDirection != (pt.x | pt.y) - && event._line == _lineNum) { + if (event._position == _currentPos && party._mazeDirection != + (_currentPos.x | _currentPos.y) && event._line == _lineNum) { if (event._direction == party._mazeDirection || event._direction == DIR_ALL) { _vm->_mode = MODE_9; _paramText = event._parameters.size() == 0 ? "" : @@ -454,8 +454,33 @@ void Scripts::cmdConfirmWord(Common::Array<byte> ¶ms) { void Scripts::cmdDamage(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdJumpRnd(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdAfterEvent(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdCallEvent(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdReturn(Common::Array<byte> ¶ms) { error("TODO"); } + +/** + * Stores the current location and line for later resuming, and set up to execute + * a script at a given location + */ +void Scripts::cmdCallEvent(Common::Array<byte> ¶ms) { + _stack.push(StackEntry(_currentPos, _lineNum)); + _currentPos = Common::Point(params[0], params[1]); + _lineNum = params[2] - 1; + + _var4F = true; + cmdNoAction(params); +} + +/** + * Return from executing a script to the script location that previously + * called the script + */ +void Scripts::cmdReturn(Common::Array<byte> ¶ms) { + StackEntry &se = _stack.top(); + _currentPos = se; + _lineNum = se.line; + + _var4F = true; + cmdNoAction(params); +} + void Scripts::cmdSetVar(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdCutsceneEndClouds(Common::Array<byte> ¶ms) { error("TODO"); } diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 5f931c1fb5..2924d43b7e 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/system.h" #include "common/serializer.h" +#include "common/stack.h" #include "common/str-array.h" #include "xeen/files.h" @@ -117,6 +118,12 @@ public: void synchronize(XeenSerializer &s); }; +struct StackEntry : public Common::Point { + int line; + + StackEntry(const Common::Point &pt, int l) : Common::Point(pt), line(l) {} +}; + class Scripts { private: XeenEngine *_vm; @@ -133,6 +140,8 @@ private: int _nEdamageType; Common::String _paramText; MazeEvent *_event; + Common::Point _currentPos; + Common::Stack<StackEntry> _stack; void doOpcode(MazeEvent &event); void cmdDisplay1(Common::Array<byte> ¶ms); -- cgit v1.2.3 From 7bfc0344210cf1ea85ccbe784ea54d172ebadc40 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 23 Jan 2015 21:33:18 -0500 Subject: XEEN: Implement cmdJumpRnd script opcode --- engines/xeen/scripts.cpp | 16 ++++++++++++++-- engines/xeen/scripts.h | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 247165f085..6a08286148 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -452,8 +452,20 @@ void Scripts::cmdConfirmWord(Common::Array<byte> ¶ms) { } void Scripts::cmdDamage(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdJumpRnd(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdAfterEvent(Common::Array<byte> ¶ms) { error("TODO"); } + +/** + * Jump if a random number matches a given value + */ +void Scripts::cmdJumpRnd(Common::Array<byte> ¶ms) { + int v = _vm->getRandomNumber(1, params[0]); + if (v == params[1]) + _lineNum = params[2] - 1; + + _var4F = true; + cmdNoAction(params); +} + +void Scripts::cmdAlterEvent(Common::Array<byte> ¶ms) { error("TODO"); } /** * Stores the current location and line for later resuming, and set up to execute diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 2924d43b7e..862c54d229 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -165,7 +165,7 @@ private: void cmdConfirmWord(Common::Array<byte> ¶ms); void cmdDamage(Common::Array<byte> ¶ms); void cmdJumpRnd(Common::Array<byte> ¶ms); - void cmdAfterEvent(Common::Array<byte> ¶ms); + void cmdAlterEvent(Common::Array<byte> ¶ms); void cmdCallEvent(Common::Array<byte> ¶ms); void cmdReturn(Common::Array<byte> ¶ms); void cmdSetVar(Common::Array<byte> ¶ms); -- cgit v1.2.3 From 06b7eb220e6f7a98007f6eb011a23b04812506b1 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 23 Jan 2015 23:47:05 -0500 Subject: XEEN: Implemented If script opcode --- engines/xeen/interface.cpp | 2 +- engines/xeen/party.cpp | 31 +++- engines/xeen/party.h | 19 ++- engines/xeen/resources.cpp | 19 +++ engines/xeen/resources.h | 2 + engines/xeen/scripts.cpp | 414 ++++++++++++++++++++++++++++++++++++++++++++- engines/xeen/scripts.h | 6 +- 7 files changed, 474 insertions(+), 19 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 307027bacc..a23cee69e5 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -355,7 +355,7 @@ void Interface::charIconsPrint(bool updateFlag) { PlayerStruct &ps = _vm->_party->_activeParty[charIndex]; // Draw the Hp bar - int maxHp = ps.getMaxHp(); + int maxHp = ps.getMaxHP(); int frame; if (ps._currentHp < 1) frame = 4; diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 8d59e686fd..43c2ecabab 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -158,17 +158,22 @@ Condition PlayerStruct::worstCondition() const { return NO_CONDITION; } -int PlayerStruct::getAge(int partyYear, bool ignoreTemp) { - int year = MIN(partyYear - _ybDay, 254); +int PlayerStruct::getAge(bool ignoreTemp) const { + int year = MIN(Party::_vm->_party->_year - _ybDay, 254); return ignoreTemp ? year : year + _tempAge; } -int PlayerStruct::getMaxHp() { +int PlayerStruct::getMaxHP() const { warning("TODO: getMaxHp"); return 20; } +int PlayerStruct::getMaxSP() const { + warning("TODO: getMaxSP"); + return 20; +} + int PlayerStruct::getStat(int statNum, int v2) { // TODO return 10; @@ -194,7 +199,7 @@ void PlayerStruct::setAward(int awardId, bool value) { _awards[v] = value; } -bool PlayerStruct::hasAward(int awardId) { +bool PlayerStruct::hasAward(int awardId) const { int v = awardId; if (awardId == 73) v = 126; @@ -204,6 +209,15 @@ bool PlayerStruct::hasAward(int awardId) { return _awards[v]; } +int PlayerStruct::getArmorClass(bool baseOnly) const { + // TODO + return 1; +} + +int PlayerStruct::getThievery() const { + // TODO + return 1; +} /*------------------------------------------------------------------------*/ @@ -217,7 +231,10 @@ void Roster::synchronize(Common::Serializer &s) { /*------------------------------------------------------------------------*/ -Party::Party(XeenEngine *vm): _vm(vm) { +XeenEngine *Party::_vm; + +Party::Party(XeenEngine *vm) { + _vm = vm; _partyCount = 0; _realPartyCount = 0; Common::fill(&_partyMembers[0], &_partyMembers[8], 0); @@ -258,7 +275,7 @@ Party::Party(XeenEngine *vm): _vm(vm) { _rested = false; Common::fill(&_gameFlags[0], &_gameFlags[512], false); - Common::fill(&_autoNotes[0], &_autoNotes[128], false); + Common::fill(&_worldFlags[0], &_worldFlags[128], false); Common::fill(&_quests[0], &_quests[64], false); Common::fill(&_questItems[0], &_questItems[85], 0); @@ -337,7 +354,7 @@ void Party::synchronize(Common::Serializer &s) { s.syncAsUint32LE(_totalTime); s.syncAsByte(_rested); SavesManager::syncBitFlags(s, &_gameFlags[0], &_gameFlags[512]); - SavesManager::syncBitFlags(s, &_autoNotes[0], &_autoNotes[128]); + SavesManager::syncBitFlags(s, &_worldFlags[0], &_worldFlags[128]); SavesManager::syncBitFlags(s, &_quests[0], &_quests[64]); for (int i = 0; i < 85; ++i) diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 3962ba45c0..2677813228 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -132,9 +132,11 @@ public: Condition worstCondition() const; - int getAge(int partyYear, bool ignoreTemp); + int getAge(bool ignoreTemp) const; - int getMaxHp(); + int getMaxHP() const; + + int getMaxSP() const; int getStat(int statNum, int v2); @@ -142,9 +144,13 @@ public: bool noActions(); - bool hasAward(int awardId); - void setAward(int awardId, bool value); + + bool hasAward(int awardId) const; + + int getArmorClass(bool baseOnly) const; + + int getThievery() const; }; class Roster: public Common::Array<PlayerStruct> { @@ -155,8 +161,9 @@ public: }; class Party { + friend class PlayerStruct; private: - XeenEngine *_vm; + static XeenEngine *_vm; public: // Dynamic data that's saved int _partyCount; @@ -204,7 +211,7 @@ public: int _totalTime; bool _rested; bool _gameFlags[512]; - bool _autoNotes[128]; + bool _worldFlags[128]; bool _quests[64]; int _questItems[85]; XeenItem _blacksmithWeapons2[ITEMS_COUNT]; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index c167bdbb48..837ff15d36 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -471,4 +471,23 @@ const int MONSTER_EFFECT_FLAGS[15][8] = { { 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108 } }; +const int SPELLS_ALLOWED[3][40] = { + { + 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, + 12, 14, 16, 23, 26, 27, 28, 30, 31, 32, + 33, 42, 46, 48, 49, 50, 52, 55, 56, 58, + 59, 62, 64, 65, 67, 68, 71, 73, 74, 76 + }, { + 1, 4, 11, 13, 15, 17, 18, 19, 20, 21, + 22, 24, 25, 29, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 47, 51, 53, 54, + 57, 60, 61, 63, 66, 69, 70, 72, 75, 76 + }, { + 0, 1, 2, 3, 4, 5, 7, 9, 10, 20, + 25, 26, 27, 28, 30, 31, 34, 38, 40, 41, + 42, 43, 44, 45, 49, 50, 52, 53, 55, 59, + 60, 61, 62, 67, 68, 72, 73, 74, 75, 76 + } +}; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index e62454eafd..36ac6b2a21 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -110,6 +110,8 @@ extern const int COMBAT_FLOAT_Y[8]; extern const int MONSTER_EFFECT_FLAGS[15][8]; +extern const int SPELLS_ALLOWED[3][40]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 6a08286148..d59346ef7e 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -23,6 +23,7 @@ #include "xeen/scripts.h" #include "xeen/dialogs_string_input.h" #include "xeen/dialogs_whowill.h" +#include "xeen/dialogs_yesno.h" #include "xeen/party.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -171,7 +172,7 @@ void Scripts::doOpcode(MazeEvent &event) { &Scripts::cmdRemove, &Scripts::cmdSetChar, &Scripts::cmdSpawn, &Scripts::cmdDoTownEvent, &Scripts::cmdExit, &Scripts::cmdAlterMap, &Scripts::cmdGiveExtended, &Scripts::cmdConfirmWord, &Scripts::cmdDamage, - &Scripts::cmdJumpRnd, &Scripts::cmdAfterEvent, &Scripts::cmdCallEvent, + &Scripts::cmdJumpRnd, &Scripts::cmdAlterEvent, &Scripts::cmdCallEvent, &Scripts::cmdReturn, &Scripts::cmdSetVar, &Scripts::cmdTakeOrGive, &Scripts::cmdTakeOrGive, &Scripts::cmdCutsceneEndClouds, &Scripts::cmdTeleport, &Scripts::cmdWhoWill, @@ -378,21 +379,47 @@ void Scripts::cmdAlterMap(Common::Array<byte> ¶ms) { } void Scripts::cmdGiveExtended(Common::Array<byte> ¶ms) { + Party &party = *_vm->_party; + uint32 mask; + int newLineNum; + bool result; + switch (params[0]) { case 16: case 34: case 100: - // TODO + mask = (params[4] << 24) | params[3] | (params[2] << 8) | (params[1] << 16); + newLineNum = params[5]; break; case 25: case 35: case 101: case 106: - // TODO + mask = (params[2] << 8) | params[1]; + newLineNum = params[3]; break; default: + mask = params[1]; + newLineNum = params[2]; break; } + + if ((_charIndex != 0 & _charIndex != 8) || params[0] == 44) { + result = ifProc(params[0], mask, _event->_opcode - OP_If1, _charIndex - 1); + } else { + result = false; + for (int idx = 0; idx < party._partyCount && !result; ++idx) { + if (_charIndex == 0 || (_charIndex == 8 && _v2 != idx)) { + result = ifProc(params[0], mask, _event->_opcode - OP_If1, idx); + } + } + } + + if (result) + _lineNum = newLineNum - 1; + + _var4F = true; + cmdNoAction(params); } void Scripts::cmdConfirmWord(Common::Array<byte> ¶ms) { @@ -634,5 +661,386 @@ void Scripts::doEnding(const Common::String &endStr, int v2) { warning("TODO: doEnding"); } +/** + * This monstrosity handles doing the various types of If checks on various data + */ +bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { + Party &party = *_vm->_party; + PlayerStruct &ps = party._activeParty[charIndex]; + uint v = 0; + + switch (action) { + case 3: + // Player sex + v = (uint)ps._sex; + break; + case 4: + // Player race + v = (uint)ps._race; + break; + case 5: + // Player class + v = (uint)ps._class; + break; + case 8: + // Current health points + v = (uint)ps._currentHp; + break; + case 9: + // Current spell points + v = (uint)ps._currentSp; + break; + case 10: + // Get armor class + v = (uint)ps.getArmorClass(false); + break; + case 11: + // Level bonus (extra beyond base) + v = ps._level._temporary; + break; + case 12: + // Current age, including unnatural aging + v = ps.getAge(false); + break; + case 13: + assert(mask < 18); + if (ps._skills[mask]) + v = mask; + break; + case 15: + // Award + assert(mask < 128); + if (ps.hasAward(mask)) + v = mask; + break; + case 16: + // Experience + v = ps._experience; + break; + case 17: + // Party poison resistence + v = party._poisonResistence; + break; + case 18: + // Condition + assert(mask < 16); + if (!ps._conditions[mask] && !(mask & 0x10)) + v = mask; + break; + case 19: { + // Can player cast a given spell + + // Get the type of character + int category; + switch (ps._class) { + case CLASS_KNIGHT: + case CLASS_ARCHER: + category = 0; + break; + case CLASS_PALADIN: + case CLASS_CLERIC: + category = 1; + break; + case CLASS_BARBARIAN: + case CLASS_DRUID: + category = 2; + break; + default: + category = 0; + break; + } + + // Check if the character class can cast the particular spell + for (int idx = 0; idx < 39; ++idx) { + if (SPELLS_ALLOWED[mode][idx] == mask) { + // Can cast it. Check if the player has it in their spellbook + if (ps._spells[idx]) + v = mask; + break; + } + } + break; + } + case 20: + if (_vm->_files->_isDarkCc) + mask += 0x100; + assert(mask < 0x200); + if (party._gameFlags[mask]) + v = mask; + break; + case 21: + // Scans inventories for given item number + v = 0xFFFFFFFF; + if (mask < 82) { + for (int idx = 0; idx < 9; ++idx) { + if (mask == 35) { + if (ps._weapons[idx]._name == mask) { + v = mask; + break; + } + } else if (mask < 49) { + if (ps._armor[idx]._name == (mask - 35)) { + v = mask; + break; + } + } else if (mask < 60) { + if (ps._accessories[idx]._name == (mask - 49)) { + v = mask; + break; + } + } else { + if (ps._misc[idx]._name == (mask - 60)) { + v = mask; + break; + } + } + } + } else { + int baseFlag = 8 * (6 + mask); + for (int idx = 0; idx < 8; ++idx) { + if (party._gameFlags[baseFlag + idx]) { + v = mask; + break; + } + } + } + break; + case 25: + // Returns number of minutes elapsed in the day (0-1440) + v = party._minutes; + break; + case 34: + // Current party gold + v = party._gold; + break; + case 35: + // Current party gems + v = party._gems; + break; + case 37: + // Might bonus (extra beond base) + v = ps._might._temporary; + break; + case 38: + // Intellect bonus (extra beyond base) + v = ps._intellect._temporary; + break; + case 39: + // Personality bonus (extra beyond base) + v = ps._personality._temporary; + break; + case 40: + // Endurance bonus (extra beyond base) + v = ps._endurance._temporary; + break; + case 41: + // Speed bonus (extra beyond base) + v = ps._speed._temporary; + break; + case 42: + // Accuracy bonus (extra beyond base) + v = ps._accuracy._temporary; + break; + case 43: + // Luck bonus (extra beyond base) + v = ps._luck._temporary; + break; + case 44: + v = YesNo::show(_vm, mask, 0); + if (!mask && v) + v = 0; + break; + case 45: + // Might base (before bonus) + v = ps._might._permanent; + break; + case 46: + // Intellect base (before bonus) + v = ps._intellect._permanent; + break; + case 47: + // Personality base (before bonus) + v = ps._personality._permanent; + break; + case 48: + // Endurance base (before bonus) + v = ps._endurance._permanent; + break; + case 49: + // Speed base (before bonus) + v = ps._speed._permanent; + break; + case 50: + // Accuracy base (before bonus) + v = ps._accuracy._permanent; + break; + case 51: + // Luck base (before bonus) + v = ps._luck._permanent; + break; + case 52: + // Fire resistence (before bonus) + v = ps._fireResistence._permanent; + break; + case 53: + // Elecricity resistence (before bonus) + v = ps._electricityResistence._permanent; + break; + case 54: + // Cold resistence (before bonus) + v = ps._coldResistence._permanent; + break; + case 55: + // Poison resistence (before bonus) + v = ps._poisonResistence._permanent; + break; + case 56: + // Energy reistence (before bonus) + v = ps._energyResistence._permanent; + break; + case 57: + // Energy resistence (before bonus) + v = ps._magicResistence._permanent; + break; + case 58: + // Fire resistence (extra beyond base) + v = ps._fireResistence._temporary; + break; + case 59: + // Electricity resistence (extra beyond base) + v = ps._electricityResistence._temporary; + break; + case 60: + // Cold resistence (extra beyond base) + v = ps._coldResistence._temporary; + break; + case 61: + // Poison resistence (extra beyod base) + v = ps._poisonResistence._temporary; + break; + case 62: + // Energy resistence (extra beyond base) + v = ps._energyResistence._temporary; + break; + case 63: + // Magic resistence (extra beyond base) + v = ps._magicResistence._temporary; + break; + case 64: + // Level (before bonus) + v = ps._level._permanent; + break; + case 65: + // Total party food + v = party._food; + break; + case 69: + // Test for Levitate being active + v = party._levitateActive ? 1 : 0; + break; + case 70: + // Amount of light + v = party._lightCount; + break; + case 71: + // Party magical fire resistence + v = party._fireResistence; + break; + case 72: + // Party magical electricity resistence + v = party._electricityResistence; + break; + case 73: + // Party magical cold resistence + v = party._coldResistence; + break; + case 76: + // Day of the year (100 per year) + v = party._day; + break; + case 77: + // Armor class (extra beyond base) + v = ps._ACTemp; + break; + case 78: + // Test whether current Hp is equal to or exceeds the max HP + v = ps._currentHp >= ps.getMaxHP() ? 1 : 0; + break; + case 79: + // Test for Wizard Eye being active + v = party._wizardEyeActive ? 1 : 0; + break; + case 81: + // Test whether current Sp is equal to or exceeds the max SP + v = ps._currentSp >= ps.getMaxSP() ? 1 : 0; + break; + case 84: + // Current facing direction + v = (uint)party._mazeDirection; + break; + case 85: + // Current game year since start + v = party._year; + break; + case 86: + case 87: + case 88: + case 89: + case 90: + case 91: + case 92: + // Get a player stat + v = ps.getStat(action - 86, 0); + break; + case 93: + // Current day of the week (10 days per week) + v = party._day / 10; + break; + case 94: + // Test whether Walk on Water is currently active + v = party._walkOnWaterActive ? 1 : 0; + break; + case 99: + // Party skills check + if (party.checkSkill((Skill)mask)) + v = mask; + break; + case 102: + // Thievery skill + v = ps.getThievery(); + break; + case 103: + // Get value of world flag + if (party._worldFlags[mask]) + v = mask; + break; + case 104: + // Get value of quest flag + if (party._quests[mask + (_vm->_files->_isDarkCc ? 30 : 0)]) + v = mask; + break; + case 105: + // Test number of Megacredits in party. Only used by King's Engineer in Castle Burlock + v = party._questItems[26]; + break; + case 107: + // Get value of character flag + error("Unused"); + break; + default: + break; + } + + switch (mode) { + case 0: + return mask >= v; + case 1: + return mask == v; + case 2: + return mask <= v; + default: + return false; + } +} } // End of namespace Xeen diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 862c54d229..fb415cac8d 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -41,8 +41,8 @@ enum Opcode { OP_NPC = 0x05, OP_PlayFX = 0x06, OP_TeleportAndExit = 0x07, - OP_If_1 = 0x08, - OP_If_2 = 0x09, + OP_If1 = 0x08, + OP_If2 = 0x09, OP_If3 = 0x0A, OP_MoveObj = 0x0B, OP_TakeOrGive = 0x0C, @@ -207,6 +207,8 @@ private: void doWorldEnd(); void doEnding(const Common::String &endStr, int v2); + + bool ifProc(int action, uint32 mask, int mode, int charIndex); public: int _animCounter; bool _eventSkipped; -- cgit v1.2.3 From 3ec43ce1cc118f1d0168f25d3d9d0c252758b629 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 00:00:20 -0500 Subject: XEEN: Implement the cmdRemove and cmdMakeNothingHere script opcodes --- engines/xeen/interface_map.h | 2 +- engines/xeen/scripts.cpp | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 914120fb2c..3ae73b76e8 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -111,7 +111,6 @@ protected: bool _flipDefaultGround; bool _isShooting; bool _charsShooting; - int _objNumber; bool _thinWall; bool _isAnimReset; int _batUIFrame; @@ -147,6 +146,7 @@ public: int _face1State; int _face2State; byte _tillMove; + int _objNumber; public: InterfaceMap(XeenEngine *vm); diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index d59346ef7e..ffe5441b2c 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -315,7 +315,18 @@ void Scripts::cmdNoAction(Common::Array<byte> ¶ms) { _lineNum = _vm->_party->_partyDead ? -1 : _lineNum + 1; } -void Scripts::cmdRemove(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdRemove(Common::Array<byte> ¶ms) { + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + + if (intf._objNumber) { + // Give the active object a completely way out of bounds position + MazeObject &obj = map._mobData._objects[intf._objNumber - 1]; + obj._position = Common::Point(128, 128); + } + + cmdMakeNothingHere(params); +} /** * Set the currently active character for other script operations @@ -545,7 +556,26 @@ void Scripts::cmdIfMapFlag(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdSelRndChar(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdGiveEnchanted(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdItemType(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdMakeNothingHere(Common::Array<byte> ¶ms) { error("TODO"); } + +/** + * Disable all the scripts at the party's current position + */ +void Scripts::cmdMakeNothingHere(Common::Array<byte> ¶ms) { + Map &map = *_vm->_map; + Party &party = *_vm->_party; + + // Scan through the event list and mark the opcodes for all the lines of any scripts + // on the party's current cell as having no operation, effectively disabling them + for (int idx = 0; idx < map._events.size(); ++idx) { + MazeEvent &evt = map._events[idx]; + if (evt._position == party._mazePosition) + evt._opcode = OP_None; + } + + _var4F = true; + cmdExit(params); +} + void Scripts::cmdNoAction2(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdChooseNumeric(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> ¶ms) { error("TODO"); } -- cgit v1.2.3 From b533822c0666ade51d2da2047e87351d3047fb58 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 09:27:48 -0500 Subject: XEEN: Implement lots of stubbed PlayerStruct methods --- engines/xeen/combat.h | 2 +- engines/xeen/items.cpp | 18 +++ engines/xeen/items.h | 4 + engines/xeen/map.cpp | 14 +- engines/xeen/party.cpp | 372 ++++++++++++++++++++++++++++++++++++++++++--- engines/xeen/party.h | 26 +++- engines/xeen/resources.cpp | 62 +++++++- engines/xeen/resources.h | 32 +++- engines/xeen/scripts.cpp | 16 +- 9 files changed, 501 insertions(+), 45 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 882f90e604..550b39fd2e 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -28,7 +28,7 @@ namespace Xeen { enum DamageType { - DT_PHYSICAL = 0, DT_1 = 1, DT_FIRE = 2, DT_ELECTRICAL = 3, + DT_PHYSICAL = 0, DT_MAGICAL = 1, DT_FIRE = 2, DT_ELECTRICAL = 3, DT_COLD = 4, DT_POISON = 5, DT_ENERGY = 6, DT_SLEEP = 7, DT_FINGEROFDEATH = 8, DT_HOLYWORD = 9, DT_MASS_DISTORTION = 10, DT_UNDED = 11, DT_BEASTMASTER = 12, DT_DRAGONSLEEP = 13, diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp index e9425f7ee9..f7dfeccbb1 100644 --- a/engines/xeen/items.cpp +++ b/engines/xeen/items.cpp @@ -21,6 +21,7 @@ */ #include "xeen/items.h" +#include "xeen/resources.h" namespace Xeen { @@ -36,6 +37,23 @@ void XeenItem::synchronize(Common::Serializer &s) { s.syncAsByte(_equipped); } +int XeenItem::getElementalCategory() const { + int idx; + for (idx = 0; ELEMENTAL_CATEGORIES[idx] < _material; ++idx) + ; + + return idx; +} + +int XeenItem::getAttributeCategory() const { + int m = _material - 59; + int idx; + for (idx = 0; ATTRIBUTE_CATEGORIES[idx] < m; ++idx) + ; + + return idx; +} + Treasure::Treasure() { _hasItems = false; } diff --git a/engines/xeen/items.h b/engines/xeen/items.h index 6fa57b922a..9141deffa2 100644 --- a/engines/xeen/items.h +++ b/engines/xeen/items.h @@ -40,6 +40,10 @@ public: XeenItem(); void synchronize(Common::Serializer &s); + + int getElementalCategory() const; + + int getAttributeCategory() const; }; class Treasure { diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index ca22b38d93..750e6347fb 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -170,7 +170,7 @@ MonsterData::MonsterData() { 10, 100, 10, 10, 10, 10, 0, 0, 0, 10, 0, false, 8, 0, 0, 117, "cleric")); push_back(MonsterStruct("Mok Heretic", 50000, 150, 12, 50, 1, CLASS_CLERIC, - 500, 1, DT_1, SA_NONE, 1, 1, MONSTER_HUMANOID, 20, 50, + 500, 1, DT_MAGICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, 20, 50, 20, 20, 20, 30, 0, 0, 0, 25, 4, false, 8, 0, 0, 117, "cleric")); push_back(MonsterStruct("Mantis Ant", 40000, 300, 30, 40, 2, CLASS_16, 2, 100, @@ -226,7 +226,7 @@ MonsterData::MonsterData() { DT_PHYSICAL, SA_NONE, 1, 0, MONSTER_0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 25, 0, 0, 131, "gremlin")); push_back(MonsterStruct("Onyx Golem", 1000000, 10000, 50, 100, 1, CLASS_15, 2, - 250, DT_1, SA_DRAINSP, 1, 0, MONSTER_GOLEM, 100, 100, + 250, DT_MAGICAL, SA_DRAINSP, 1, 0, MONSTER_GOLEM, 100, 100, 100, 100, 100, 100, 50, 0, 0, 100, 0, true, 24, 0, 10, 100, "golem")); push_back(MonsterStruct("Gremlin", 2000, 20, 7, 35, 2, CLASS_16, 2, 10, @@ -260,7 +260,7 @@ MonsterData::MonsterData() { DT_FIRE, SA_NONE, 1, 0, MONSTER_INSECT, 100, 100, 0, 100, 0, 0, 0, 0, 0, 0, 0, false, 33, 0, 0, 131, "Phantom")); push_back(MonsterStruct("Power Lich", 200000, 500, 20, 60, 1, CLASS_15, 10, 10, - DT_1, SA_UNCONSCIOUS, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0, + DT_MAGICAL, SA_UNCONSCIOUS, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0, 0, 80, 70, 0, 0, 0, 0, true, 34, 0, 0, 141, "lich")); push_back(MonsterStruct("Mystic Mage", 100000, 200, 20, 70, 1, CLASS_15, 10, 20, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_0, 50, 100, @@ -317,7 +317,7 @@ MonsterData::MonsterData() { 10, 100, 10, 10, 10, 20, 0, 0, 0, 20, 0, false, 50, 0, 0, 163, "disint")); push_back(MonsterStruct("Sorceress", 80000, 200, 30, 80, 1, CLASS_15, 2, 50, - DT_1, SA_NONE, 1, 1, MONSTER_HUMANOID, 10, 20, 10, 10, + DT_MAGICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, 10, 20, 10, 10, 10, 80, 0, 0, 0, 50, 5, false, 50, 0, 0, 163, "disint")); push_back(MonsterStruct("Arachnoid", 4000, 50, 10, 40, 1, CLASS_16, 3, 5, DT_POISON, SA_POISON, 1, 0, MONSTER_INSECT, 0, 0, 0, @@ -367,7 +367,7 @@ MonsterData::MonsterData() { 50, 50, 50, 50, 50, 0, 0, 0, 50, 0, false, 64, 0, 0, 163, "boltelec")); push_back(MonsterStruct("Wizard", 60000, 250, 20, 125, 1, CLASS_PALADIN, 10, - 25, DT_1, SA_NONE, 1, 1, MONSTER_HUMANOID, 50, 30, 30, + 25, DT_MAGICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, 50, 30, 30, 30, 30, 30, 0, 0, 0, 20, 0, false, 65, 0, 0, 163, "wizard")); push_back(MonsterStruct("Dark Wolf", 10000, 70, 10, 70, 3, CLASS_16, 3, 8, DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_ANIMAL, 0, 0, 0, @@ -391,7 +391,7 @@ MonsterData::MonsterData() { MONSTER_HUMANOID, 80, 80, 80, 80, 80, 20, 0, 0, 200, 0, 7, false, 30, 0, 10, 100, "knight")); push_back(MonsterStruct("Sandro", 200000, 1000, 20, 75, 1, CLASS_15, 10, 10, - DT_1, SA_DEATH, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0, 0, + DT_MAGICAL, SA_DEATH, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0, 0, 90, 80, 0, 0, 100, 7, true, 34, 0, 10, 100, "lich")); push_back(MonsterStruct("Mega Mage", 500000, 500, 35, 100, 1, CLASS_15, 10, 40, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_0, 80, 100, 80, @@ -439,7 +439,7 @@ MonsterData::MonsterData() { 0, MONSTER_UNDEAD, 80, 80, 80, 80, 80, 80, 90, 0, 0, 0, 0, false, 58, 0, 0, 100, "vamp")); push_back(MonsterStruct("Valio", 60000, 150, 15, 60, 1, CLASS_PALADIN, 10, 25, - DT_1, SA_NONE, 1, 0, MONSTER_HUMANOID, 50, 30, 30, 30, + DT_MAGICAL, SA_NONE, 1, 0, MONSTER_HUMANOID, 50, 30, 30, 30, 40, 30, 0, 0, 0, 0, 0, false, 65, 0, 0, 100, "wizard")); push_back(MonsterStruct("Sky Golem", 200000, 1000, 50, 100, 1, CLASS_15, 2, 100, DT_COLD, SA_NONE, 1, 1, MONSTER_GOLEM, 50, 50, diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 43c2ecabab..b19e39aa2e 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -165,28 +165,194 @@ int PlayerStruct::getAge(bool ignoreTemp) const { } int PlayerStruct::getMaxHP() const { - warning("TODO: getMaxHp"); - return 20; + int hp = BASE_HP_BY_CLASS[_class]; + hp += statBonus(getStat(ENDURANCE, false)); + hp += RACE_HP_BONUSES[_race]; + if (_skills[BODYBUILDER]) + ++hp; + if (hp < 1) + hp = 1; + + hp *= getCurrentLevel(); + hp += itemScan(7); + + if (hp < 0) + hp = 0; + + return hp; } int PlayerStruct::getMaxSP() const { - warning("TODO: getMaxSP"); - return 20; + int result = 0; + bool flag = false; + int amount; + Attribute attrib; + Skill skill; + + if (_hasSpells) + return 0; + + if (_class == CLASS_SORCERER || _class == CLASS_ARCHER) { + attrib = INTELLECT; + skill = PRESTIDIGITATION; + } else { + attrib = PERSONALITY; + skill = PRAYER_MASTER; + } + if (_class == CLASS_DRUID || _class == CLASS_RANGER) + skill = ASTROLOGER; + + for (;;) { + // Get the base number of spell points + result = statBonus(getStat(attrib, false)); + result += RACE_SP_BONUSES[_race][attrib - 1]; + + if (_skills[skill]) + result += 2; + if (result < 1) + result = 1; + + // Multiply it by the character's level + result *= getCurrentLevel(); + + // Classes other than sorcerer, clerics, and druids only get half the SP + if (_class != CLASS_SORCERER && _class != CLASS_CLERIC && _class != CLASS_DRUID) + result /= 2; + + if (flag || (_class != CLASS_DRUID && _class != CLASS_RANGER)) + break; + + // Druids and rangers get bonuses averaged on both personality and intellect + attrib = INTELLECT; + flag = true; + amount = result; + } + if (flag) + result = (amount + result) / 2; + + result += itemScan(8); + if (result < 0) + result = 0; + + return result; +} + +/** + * Get the effective value of a given stat for the character + */ +int PlayerStruct::getStat(Attribute attrib, bool applyMod) const { + AttributePair attr; + int mode = 0; + + switch (attrib) { + case MIGHT: + attr = _might; + break; + case INTELLECT: + attr = _intellect; + mode = 1; + break; + case PERSONALITY: + attr = _personality; + mode = 1; + break; + case ENDURANCE: + attr = _endurance; + break; + case SPEED: + attr = _speed; + break; + case ACCURACY: + attr = _accuracy; + break; + case LUCK: + attr = _luck; + mode = 2; + break; + default: + return 0; + } + + // All the attributes except luck are affected by the character's age + if (mode < 2) { + int age = getAge(false); + int ageIndex = 0; + while (AGE_RANGES[ageIndex] < age) + ++ageIndex; + + attr._permanent += AGE_RANGES_ADJUST[mode][ageIndex]; + } + + if (applyMod) { + attr._permanent += conditionMod(attrib); + attr._permanent += attr._temporary; + } + + return (attr._permanent >= 1) ? attr._permanent : 0; } -int PlayerStruct::getStat(int statNum, int v2) { - // TODO - return 10; +int PlayerStruct::statBonus(int statValue) const { + for (int idx = 0; STAT_VALUES[idx] <= statValue; ++idx) + return STAT_BONUSES[idx]; + + return 0; } -bool PlayerStruct::charSavingThrow() { - // TODO - return false; +bool PlayerStruct::charSavingThrow(DamageType attackType) const { + int v, vMax; + + if (attackType == DT_PHYSICAL) { + v = statBonus(getStat(LUCK, false)) + getCurrentLevel(); + vMax = v + 20; + } else { + switch (attackType) { + case DT_MAGICAL: + v = _magicResistence._permanent + _magicResistence._temporary + itemScan(16); + break; + case DT_FIRE: + v = _fireResistence._permanent + _fireResistence._temporary + itemScan(11); + break; + case DT_ELECTRICAL: + v = _electricityResistence._permanent + _electricityResistence._temporary + itemScan(12); + break; + case DT_COLD: + v = _coldResistence._permanent + _coldResistence._temporary + itemScan(13); + break; + case DT_POISON: + v = _poisonResistence._permanent + _poisonResistence._temporary + itemScan(14); + break; + case DT_ENERGY: + v = _energyResistence._permanent + _energyResistence._temporary + itemScan(15); + break; + default: + v = 0; + break; + } + + vMax = v + 40; + } + + return Party::_vm->getRandomNumber(1, vMax) <= v; } bool PlayerStruct::noActions() { - // TODO - return false; + Condition condition = worstCondition(); + + switch (condition) { + case CURSED: + case POISONED: + case DISEASED: + case INSANE: + case IN_LOVE: + case DRUNK: { + Common::String msg = Common::String::format(IN_NO_CONDITION, _name.c_str()); + ErrorScroll::show(Party::_vm, msg, + Party::_vm->_mode == 17 ? WT_2 : WT_NONFREEZED_WAIT); + return true; + } + default: + return false; + } } void PlayerStruct::setAward(int awardId, bool value) { @@ -210,13 +376,177 @@ bool PlayerStruct::hasAward(int awardId) const { } int PlayerStruct::getArmorClass(bool baseOnly) const { - // TODO - return 1; + Party &party = *Party::_vm->_party; + + int result = statBonus(getStat(SPEED, false)) + itemScan(9); + if (!baseOnly) + result += (party._blessedActive ? 1 : 0) + _ACTemp; + + return MAX(result, 0); } +/** + * Returns the thievery skill level, adjusted by class and race + */ int PlayerStruct::getThievery() const { - // TODO - return 1; + int result = getCurrentLevel() * 2; + + if (_class == CLASS_NINJA) + result += 15; + else if (_class == CLASS_ROBBER) + result += 30; + + switch (_race) { + case ELF: + case GNOME: + result += 10; + break; + case DWARF: + result += 5; + break; + case HALF_ORC: + result -= 10; + break; + default: + break; + } + + result += itemScan(10); + + // If the character doesn't have a thievery skill, then do'nt allow any result + if (!_skills[THIEVERY]) + result = 0; + + return MAX(result, 0); +} + +int PlayerStruct::getCurrentLevel() const { + return MAX(_level._permanent + _level._temporary, 0); +} + +int PlayerStruct::itemScan(int itemId) const { + int result = 0; + + for (int accessIdx = 0; accessIdx < 3; ++accessIdx) { + switch (accessIdx) { + case 0: + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + const XeenItem &item = _weapons[idx]; + + if (item._equipped && !(item._bonusFlags & 0xC0) && itemId < 11 + && itemId != 3 && item._material >= 59 && item._material <= 130) { + int mIndex = item.getAttributeCategory(); + if (mIndex > 2) + ++mIndex; + + if (mIndex == itemId) + result += ATTRIBUTE_BONUSES[item._material - 59]; + } + } + break; + + case 1: + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + const XeenItem &item = _armor[idx]; + + if (item._equipped && !(item._bonusFlags & 0xC0)) { + if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) { + int mIndex = item.getAttributeCategory(); + if (mIndex > 2) + ++mIndex; + + if (mIndex == itemId) + result += ATTRIBUTE_BONUSES[item._material - 59]; + } + + if (itemId > 10 && item._material < 37) { + int mIndex = item.getElementalCategory() + 11; + + if (mIndex == itemId) { + result += ELEMENTAL_RESISTENCES[item._material]; + } + } + + if (itemId == 9) { + result += ARMOR_STRENGTHS[item._name]; + + if (item._material >= 37 && item._material <= 58) + result += METAL_LAC[item._material - 37]; + } + } + } + break; + + case 2: + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + const XeenItem &item = _accessories[idx]; + + if (item._equipped && !(item._bonusFlags & 0xC0) && itemId < 11 && itemId != 3) { + if (item._material >= 59 && item._material <= 130) { + int mIndex = item.getAttributeCategory(); + if (mIndex > 2) + ++mIndex; + + if (mIndex == itemId) { + result += ATTRIBUTE_BONUSES[item._material - 59]; + } + } + + if (itemId > 10 && item._material < 37) { + int mIndex = item.getElementalCategory() + 11; + + if (mIndex == itemId) + result += ELEMENTAL_RESISTENCES[item._material]; + } + } + } + break; + } + }; + + return result; +} + +/** + * Modifies a passed attribute value based on player's condition + */ +int PlayerStruct::conditionMod(Attribute attrib) const { + if (_conditions[DEAD] || _conditions[STONED] || _conditions[ERADICATED]) + return 0; + + int v[7]; + Common::fill(&v[0], &v[7], 0); + if (_conditions[CURSED]) + v[6] -= _conditions[CURSED]; + + if (_conditions[INSANE]) { + v[2] -= _conditions[INSANE]; + v[1] -= _conditions[INSANE]; + v[5] -= _conditions[INSANE]; + v[0] -= _conditions[INSANE]; + v[4] -= _conditions[INSANE]; + } + + if (_conditions[POISONED]) { + v[0] -= _conditions[POISONED]; + v[4] -= _conditions[POISONED]; + v[5] -= _conditions[POISONED]; + } + + if (_conditions[DISEASED]) { + v[3] -= _conditions[DISEASED]; + v[2] -= _conditions[DISEASED]; + v[1] -= _conditions[DISEASED]; + } + + for (int idx = 0; idx < 7; ++idx) { + v[idx] -= _conditions[HEART_BROKEN]; + v[idx] -= _conditions[IN_LOVE]; + v[idx] -= _conditions[WEAK]; + v[idx] -= _conditions[DRUNK]; + } + + return v[attrib]; } /*------------------------------------------------------------------------*/ @@ -432,7 +762,7 @@ void Party::changeTime(int numMinutes) { if (!player._conditions[DEAD] && !player._conditions[STONED] && !player._conditions[ERADICATED]) { for (int statNum = 0; statNum < TOTAL_STATS; ++statNum) { - int statVal = player.getStat(statNum, 0); + int statVal = player.getStat((Attribute)statNum, false); if (statVal < 1) player._conditions[DEAD] = 1; } @@ -448,16 +778,16 @@ void Party::changeTime(int numMinutes) { // Handle poisoning if (!player._conditions[POISONED]) { - if (_vm->getRandomNumber(9) != 1 || !player.charSavingThrow()) + if (_vm->getRandomNumber(1, 10) != 1 || !player.charSavingThrow(DT_ELECTRICAL)) player._conditions[POISONED] *= 2; else // Poison wears off player._conditions[POISONED] = 0; } - // Handle poisoning + // Handle disease if (!player._conditions[DISEASED]) { - if (_vm->getRandomNumber(9) != 1 || !player.charSavingThrow()) + if (_vm->getRandomNumber(9) != 1 || !player.charSavingThrow(DT_COLD)) player._conditions[DISEASED] *= 2; else // Disease wears off @@ -506,7 +836,7 @@ void Party::changeTime(int numMinutes) { PlayerStruct &player = _activeParty[idx]; if (player._conditions[CONFUSED] && _vm->getRandomNumber(2) == 1) { - if (player.charSavingThrow()) { + if (player.charSavingThrow(DT_PHYSICAL)) { player._conditions[CONFUSED] = 0; } else { player._conditions[CONFUSED]--; diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 2677813228..5d35b0f726 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -49,6 +49,11 @@ enum CharacterClass { CLASS_12 = 12, CLASS_15 = 15, CLASS_16 = 16 }; +enum Attribute{ + MIGHT = 0, INTELLECT = 1, PERSONALITY = 2, ENDURANCE = 3, SPEED = 4, + ACCURACY = 5, LUCK = 6 +}; + enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3, CARTOGRAPHER = 4, CRUSADER = 5, DIRECTION_SENSE = 6, LINGUIST = 7, MERCHANT = 8, MOUNTAINEER = 9, NAVIGATOR = 10, PATHFINDER = 11, @@ -68,6 +73,7 @@ enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, #define XEEN_TOTAL_CHARACTERS 24 #define MAX_ACTIVE_PARTY 6 #define TOTAL_STATS 7 +#define INV_ITEMS_TOTAL 9 class XeenEngine; @@ -81,6 +87,8 @@ public: }; class PlayerStruct { +private: + int conditionMod(Attribute attrib) const; public: Common::String _name; Sex _sex; @@ -106,10 +114,10 @@ public: bool _hasSpells; int _currentSpell; int _quickOption; - XeenItem _weapons[9]; - XeenItem _armor[9]; - XeenItem _accessories[9]; - XeenItem _misc[9]; + XeenItem _weapons[INV_ITEMS_TOTAL]; + XeenItem _armor[INV_ITEMS_TOTAL]; + XeenItem _accessories[INV_ITEMS_TOTAL]; + XeenItem _misc[INV_ITEMS_TOTAL]; int _lloydSide; AttributePair _fireResistence; AttributePair _coldResistence; @@ -138,9 +146,11 @@ public: int getMaxSP() const; - int getStat(int statNum, int v2); + int getStat(Attribute attrib, bool applyMod) const; - bool charSavingThrow(); + int statBonus(int statValue) const; + + bool charSavingThrow(DamageType attackType) const; bool noActions(); @@ -151,6 +161,10 @@ public: int getArmorClass(bool baseOnly) const; int getThievery() const; + + int getCurrentLevel() const; + + int itemScan(int itemId) const; }; class Roster: public Common::Array<PlayerStruct> { diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 837ff15d36..993bf2f546 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -73,6 +73,8 @@ const char *const WHO_WILL = "\X03""c\X0B""000\x09""000%s\x0A\x0A" const char *const WHATS_THE_PASSWORD = "What's the Password?"; +const char *const IN_NO_CONDITION = "\x0B""007%s is not in any condition to perform actions!"; + const char *const TERRAIN_TYPES[6] = { "town", "cave", "towr", "cstl", "dung", "scfi" }; @@ -271,6 +273,12 @@ const char *const DIRECTION_TEXT[4] = { "NORTH", "EAST", "SOUTH", "WEST" }; const char *const RACE_NAMES[5] = { "Human", "Elf", "Dwarf", "Gnome", "H-Orc" }; +const int RACE_HP_BONUSES[5] = { 0, -2, 1, -1, 2 }; + +const int RACE_SP_BONUSES[5][2] = { + { 0, 0 }, { 2, 0 }, { -1, -1 }, { 1, 1 }, { -2, -2 } +}; + const char *const ALIGNMENT_NAMES[3] = { "Good", "Neutral", "Evil" }; const char *const SEX_NAMES[2] = { "Male", "Female" }; @@ -471,7 +479,7 @@ const int MONSTER_EFFECT_FLAGS[15][8] = { { 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108 } }; -const int SPELLS_ALLOWED[3][40] = { +const uint SPELLS_ALLOWED[3][40] = { { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 14, 16, 23, 26, 27, 28, 30, 31, 32, @@ -490,4 +498,56 @@ const int SPELLS_ALLOWED[3][40] = { } }; +const int BASE_HP_BY_CLASS[10] = { 10, 8, 7, 5, 4, 8, 7, 12, 6, 9 }; + +const int AGE_RANGES[10] = { 1, 6, 11, 18, 36, 51, 76, 101, 201, 0xffff }; + +const int AGE_RANGES_ADJUST[2][10] = { + { -250, -50, -20, -10, 0, -2, -5, -10, -20, -50 }, + { -250, -50, -20, -10, 0, 2, 5, 10, 20, 50 } +}; + +const int STAT_VALUES[24] = { + 11, 13, 15, 17, 19, 21, 25, 30, 35, 40, 50, 75, + 100, 125, 150, 175, 200, 225, 250, 65535 +}; + +const int STAT_BONUSES[24] = { + 251, 252, 253, 254, 255, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20 +}; + +const int ELEMENTAL_CATEGORIES[6] = { 8, 15, 20, 25, 33, 36 }; + +const int ATTRIBUTE_CATEGORIES[10] = { + 9, 17, 25, 33, 39, 45, 50, 56, 61, 72 }; + +const int ATTRIBUTE_BONUSES[72] = { + 2, 3, 5, 8, 12, 17, 23, 30, 38, 47, // Might bonus + 2, 3, 5, 8, 12, 17, 23, 30, // INT bonus + 2, 3, 5, 8, 12, 17, 23, 30, // PER bonus + 2, 3, 5, 8, 12, 17, 23, 30, // SPD bonus + 3, 5, 10, 15, 20, 30, // ACC bonus + 5, 10, 15, 20, 25, 30, // LUC bonus + 4, 6, 10, 20, 50, // HP bonus + 4, 8, 12, 16, 20, 25, // SP bonus + 2, 4, 6, 10, 16, // AC bonus + 4, 6, 8, 10, 12, 14, 16, 18, 20, 25 // Thievery bonus +}; + +const int ELEMENTAL_RESISTENCES[37] = { + 0, 5, 7, 9, 12, 15, 20, 25, 30, 5, 7, 9, 12, 15, 20, 25, + 5, 10, 15, 20, 25, 10, 15, 20, 25, 40, 5, 7, 9, 11, 13, 15, 20, 25, + 5, 10, 20 +}; + +const int ELEMENTAL_DAMAGE[37] = { + 0, 2, 3, 4, 5, 10, 15, 20, 30, 2, 3, 4, 5, 10, 15, 20, 2, 4, 5, 10, 20, + 2, 4, 8, 16, 32, 2, 3, 4, 5, 10, 15, 20, 30, 5, 10, 25 +}; + +const int METAL_LAC[9] = { -3, 0, -2, -1, 1, 2, 4, 6, 8 }; + +const int ARMOR_STRENGTHS[14] = { 0, 2, 4, 5, 6, 7, 8, 10, 4, 2, 1, 1, 1, 1 }; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 36ac6b2a21..b1c972069c 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -38,6 +38,8 @@ extern const char *const WHO_WILL; extern const char *const WHATS_THE_PASSWORD; +extern const char *const IN_NO_CONDITION; + extern const char *const TERRAIN_TYPES[6]; extern const char *const SURFACE_TYPE_NAMES[15]; @@ -56,6 +58,10 @@ extern const char *const DIRECTION_TEXT[4]; extern const char *const RACE_NAMES[5]; +extern const int RACE_HP_BONUSES[5]; + +extern const int RACE_SP_BONUSES[5][2]; + extern const char *const CLASS_NAMES[11]; extern const char *const ALIGNMENT_NAMES[3]; @@ -110,7 +116,31 @@ extern const int COMBAT_FLOAT_Y[8]; extern const int MONSTER_EFFECT_FLAGS[15][8]; -extern const int SPELLS_ALLOWED[3][40]; +extern const uint SPELLS_ALLOWED[3][40]; + +extern const int BASE_HP_BY_CLASS[10]; + +extern const int AGE_RANGES[10]; + +extern const int AGE_RANGES_ADJUST[2][10]; + +extern const int STAT_VALUES[24]; + +extern const int STAT_BONUSES[24]; + +extern const int ELEMENTAL_CATEGORIES[6]; + +extern const int ATTRIBUTE_CATEGORIES[10]; + +extern const int ATTRIBUTE_BONUSES[72]; + +extern const int ELEMENTAL_RESISTENCES[37]; + +extern const int ELEMENTAL_DAMAGE[37]; + +extern const int METAL_LAC[9]; + +extern const int ARMOR_STRENGTHS[14]; } // End of namespace Xeen diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index ffe5441b2c..6f14be20b7 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -86,7 +86,7 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) { void Scripts::checkEvents() { Combat &combat = *_vm->_combat; - Interface &intf = *_vm->_interface; +// Interface &intf = *_vm->_interface; Map &map = *_vm->_map; Party &party = *_vm->_party; @@ -415,7 +415,7 @@ void Scripts::cmdGiveExtended(Common::Array<byte> ¶ms) { break; } - if ((_charIndex != 0 & _charIndex != 8) || params[0] == 44) { + if ((_charIndex != 0 && _charIndex != 8) || params[0] == 44) { result = ifProc(params[0], mask, _event->_opcode - OP_If1, _charIndex - 1); } else { result = false; @@ -566,7 +566,7 @@ void Scripts::cmdMakeNothingHere(Common::Array<byte> ¶ms) { // Scan through the event list and mark the opcodes for all the lines of any scripts // on the party's current cell as having no operation, effectively disabling them - for (int idx = 0; idx < map._events.size(); ++idx) { + for (uint idx = 0; idx < map._events.size(); ++idx) { MazeEvent &evt = map._events[idx]; if (evt._position == party._mazePosition) evt._opcode = OP_None; @@ -804,22 +804,22 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { if (mask < 82) { for (int idx = 0; idx < 9; ++idx) { if (mask == 35) { - if (ps._weapons[idx]._name == mask) { + if ((int)ps._weapons[idx]._name == mask) { v = mask; break; } } else if (mask < 49) { - if (ps._armor[idx]._name == (mask - 35)) { + if ((int)ps._armor[idx]._name == (mask - 35)) { v = mask; break; } } else if (mask < 60) { - if (ps._accessories[idx]._name == (mask - 49)) { + if ((int)ps._accessories[idx]._name == (mask - 49)) { v = mask; break; } } else { - if (ps._misc[idx]._name == (mask - 60)) { + if ((int)ps._misc[idx]._name == (mask - 60)) { v = mask; break; } @@ -1020,7 +1020,7 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { case 91: case 92: // Get a player stat - v = ps.getStat(action - 86, 0); + v = ps.getStat((Attribute)(action - 86), 0); break; case 93: // Current day of the week (10 days per week) -- cgit v1.2.3 From 1f8a5ea24a8c031979289953fdb674029338d9bc Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 09:29:17 -0500 Subject: XEEN: Changed PlayerStruct to Character --- engines/xeen/interface.cpp | 8 ++++---- engines/xeen/party.cpp | 40 ++++++++++++++++++++-------------------- engines/xeen/party.h | 10 +++++----- engines/xeen/scripts.cpp | 4 ++-- 4 files changed, 31 insertions(+), 31 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index a23cee69e5..44e2326c1f 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -106,7 +106,7 @@ start: // Build up a list of characters on the same Xeen side being loaded for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { - PlayerStruct &player = _vm->_roster[i]; + Character &player = _vm->_roster[i]; if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0)) continue; @@ -300,7 +300,7 @@ void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool Common::Rect &b = _buttons[7 + posIndex]._bounds; b.moveTo((posIndex & 1) ? 117 : 16, b.top); - PlayerStruct &ps = _vm->_roster[xeenSideChars[charIndex + posIndex]]; + Character &ps = _vm->_roster[xeenSideChars[charIndex + posIndex]]; playerNames[posIndex] = isInParty ? IN_PARTY : ps._name; playerRaces[posIndex] = RACE_NAMES[ps._race]; playerSex[posIndex] = SEX_NAMES[ps._sex]; @@ -336,7 +336,7 @@ void Interface::charIconsPrint(bool updateFlag) { for (int idx = 0; idx < (stateFlag ? _vm->_party->_combatPartyCount : _vm->_party->_partyCount); ++idx) { int charIndex = stateFlag ? _combatCharIds[idx] : idx; - PlayerStruct &ps = _vm->_party->_activeParty[charIndex]; + Character &ps = _vm->_party->_activeParty[charIndex]; Condition charCondition = ps.worstCondition(); int charFrame = FACE_CONDITION_FRAMES[charCondition]; @@ -352,7 +352,7 @@ void Interface::charIconsPrint(bool updateFlag) { for (int idx = 0; idx < (stateFlag ? _vm->_party->_combatPartyCount : _vm->_party->_partyCount); ++idx) { int charIndex = stateFlag ? _combatCharIds[idx] : idx; - PlayerStruct &ps = _vm->_party->_activeParty[charIndex]; + Character &ps = _vm->_party->_activeParty[charIndex]; // Draw the Hp bar int maxHp = ps.getMaxHP(); diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index b19e39aa2e..791a19ff4f 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -42,7 +42,7 @@ void AttributePair::synchronize(Common::Serializer &s) { /*------------------------------------------------------------------------*/ -PlayerStruct::PlayerStruct() { +Character::Character() { _sex = MALE; _race = HUMAN; _xeenSide = 0; @@ -69,7 +69,7 @@ PlayerStruct::PlayerStruct() { _currentCombatSpell = 0; } -void PlayerStruct::synchronize(Common::Serializer &s) { +void Character::synchronize(Common::Serializer &s) { char name[16]; Common::fill(&name[0], &name[16], '\0'); strncpy(name, _name.c_str(), 16); @@ -149,7 +149,7 @@ void PlayerStruct::synchronize(Common::Serializer &s) { s.syncAsByte(_currentCombatSpell); } -Condition PlayerStruct::worstCondition() const { +Condition Character::worstCondition() const { for (int cond = ERADICATED; cond >= CURSED; --cond) { if (_conditions[cond]) return (Condition)cond; @@ -158,13 +158,13 @@ Condition PlayerStruct::worstCondition() const { return NO_CONDITION; } -int PlayerStruct::getAge(bool ignoreTemp) const { +int Character::getAge(bool ignoreTemp) const { int year = MIN(Party::_vm->_party->_year - _ybDay, 254); return ignoreTemp ? year : year + _tempAge; } -int PlayerStruct::getMaxHP() const { +int Character::getMaxHP() const { int hp = BASE_HP_BY_CLASS[_class]; hp += statBonus(getStat(ENDURANCE, false)); hp += RACE_HP_BONUSES[_race]; @@ -182,7 +182,7 @@ int PlayerStruct::getMaxHP() const { return hp; } -int PlayerStruct::getMaxSP() const { +int Character::getMaxSP() const { int result = 0; bool flag = false; int amount; @@ -240,7 +240,7 @@ int PlayerStruct::getMaxSP() const { /** * Get the effective value of a given stat for the character */ -int PlayerStruct::getStat(Attribute attrib, bool applyMod) const { +int Character::getStat(Attribute attrib, bool applyMod) const { AttributePair attr; int mode = 0; @@ -291,14 +291,14 @@ int PlayerStruct::getStat(Attribute attrib, bool applyMod) const { return (attr._permanent >= 1) ? attr._permanent : 0; } -int PlayerStruct::statBonus(int statValue) const { +int Character::statBonus(int statValue) const { for (int idx = 0; STAT_VALUES[idx] <= statValue; ++idx) return STAT_BONUSES[idx]; return 0; } -bool PlayerStruct::charSavingThrow(DamageType attackType) const { +bool Character::charSavingThrow(DamageType attackType) const { int v, vMax; if (attackType == DT_PHYSICAL) { @@ -335,7 +335,7 @@ bool PlayerStruct::charSavingThrow(DamageType attackType) const { return Party::_vm->getRandomNumber(1, vMax) <= v; } -bool PlayerStruct::noActions() { +bool Character::noActions() { Condition condition = worstCondition(); switch (condition) { @@ -355,7 +355,7 @@ bool PlayerStruct::noActions() { } } -void PlayerStruct::setAward(int awardId, bool value) { +void Character::setAward(int awardId, bool value) { int v = awardId; if (awardId == 73) v = 126; @@ -365,7 +365,7 @@ void PlayerStruct::setAward(int awardId, bool value) { _awards[v] = value; } -bool PlayerStruct::hasAward(int awardId) const { +bool Character::hasAward(int awardId) const { int v = awardId; if (awardId == 73) v = 126; @@ -375,7 +375,7 @@ bool PlayerStruct::hasAward(int awardId) const { return _awards[v]; } -int PlayerStruct::getArmorClass(bool baseOnly) const { +int Character::getArmorClass(bool baseOnly) const { Party &party = *Party::_vm->_party; int result = statBonus(getStat(SPEED, false)) + itemScan(9); @@ -388,7 +388,7 @@ int PlayerStruct::getArmorClass(bool baseOnly) const { /** * Returns the thievery skill level, adjusted by class and race */ -int PlayerStruct::getThievery() const { +int Character::getThievery() const { int result = getCurrentLevel() * 2; if (_class == CLASS_NINJA) @@ -420,11 +420,11 @@ int PlayerStruct::getThievery() const { return MAX(result, 0); } -int PlayerStruct::getCurrentLevel() const { +int Character::getCurrentLevel() const { return MAX(_level._permanent + _level._temporary, 0); } -int PlayerStruct::itemScan(int itemId) const { +int Character::itemScan(int itemId) const { int result = 0; for (int accessIdx = 0; accessIdx < 3; ++accessIdx) { @@ -510,7 +510,7 @@ int PlayerStruct::itemScan(int itemId) const { /** * Modifies a passed attribute value based on player's condition */ -int PlayerStruct::conditionMod(Attribute attrib) const { +int Character::conditionMod(Attribute attrib) const { if (_conditions[DEAD] || _conditions[STONED] || _conditions[ERADICATED]) return 0; @@ -757,7 +757,7 @@ void Party::changeTime(int numMinutes) { if (((_minutes + numMinutes) / 480) != (_minutes / 480)) { for (int idx = 0; idx < _partyCount; ++idx) { - PlayerStruct &player = _activeParty[idx]; + Character &player = _activeParty[idx]; if (!player._conditions[DEAD] && !player._conditions[STONED] && !player._conditions[ERADICATED]) { @@ -833,7 +833,7 @@ void Party::changeTime(int numMinutes) { addTime(numMinutes); for (int idx = 0; idx < _partyCount; ++idx) { - PlayerStruct &player = _activeParty[idx]; + Character &player = _activeParty[idx]; if (player._conditions[CONFUSED] && _vm->getRandomNumber(2) == 1) { if (player.charSavingThrow(DT_PHYSICAL)) { @@ -899,7 +899,7 @@ void Party::addTime(int numMinutes) { void Party::resetTemps() { for (int idx = 0; idx < _partyCount; ++idx) { - PlayerStruct &player = _activeParty[idx]; + Character &player = _activeParty[idx]; player._magicResistence._temporary = 0; player._energyResistence._temporary = 0; diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 5d35b0f726..f56190982d 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -86,7 +86,7 @@ public: void synchronize(Common::Serializer &s); }; -class PlayerStruct { +class Character { private: int conditionMod(Attribute attrib) const; public: @@ -135,7 +135,7 @@ public: int _currentAdventuringSpell; int _currentCombatSpell; public: - PlayerStruct(); + Character(); void synchronize(Common::Serializer &s); Condition worstCondition() const; @@ -167,7 +167,7 @@ public: int itemScan(int itemId) const; }; -class Roster: public Common::Array<PlayerStruct> { +class Roster: public Common::Array<Character> { public: Roster() {} @@ -175,7 +175,7 @@ public: }; class Party { - friend class PlayerStruct; + friend class Character; private: static XeenEngine *_vm; public: @@ -235,7 +235,7 @@ public: bool _characterFlags[30][24]; public: // Other party related runtime data - Common::Array<PlayerStruct> _activeParty; + Common::Array<Character> _activeParty; int _combatPartyCount; bool _partyDead; bool _newDay; diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 6f14be20b7..10ba972d8d 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -667,7 +667,7 @@ void Scripts::doEndGame2() { int v2 = 0; for (int idx = 0; idx < party._partyCount; ++idx) { - PlayerStruct &player = party._activeParty[idx]; + Character &player = party._activeParty[idx]; if (player.hasAward(77)) { v2 = 2; break; @@ -696,7 +696,7 @@ void Scripts::doEnding(const Common::String &endStr, int v2) { */ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { Party &party = *_vm->_party; - PlayerStruct &ps = party._activeParty[charIndex]; + Character &ps = party._activeParty[charIndex]; uint v = 0; switch (action) { -- cgit v1.2.3 From 2b5167cafcebe78e797318690080e2ed3706da28 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 09:35:56 -0500 Subject: XEEN: Fix side loading bug in Map::load --- engines/xeen/map.cpp | 10 +++++----- engines/xeen/map.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 750e6347fb..4adf356a0c 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -857,8 +857,8 @@ void AnimationInfo::load(const Common::String &name) { /*------------------------------------------------------------------------*/ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { - _townPortalSide = false; _loadDarkSide = false; + _sideTownPortal = 0; _sideObjects = 0; _sideMonsters = 0; _sidePictures = 0; @@ -897,13 +897,13 @@ void Map::load(int mapId) { _sideMonsters = 1; _sidePictures = 1; if (mapId >= 113 && mapId <= 127) { - _townPortalSide = false; + _sideTownPortal = 0; } else { - _townPortalSide = _loadDarkSide; + _sideTownPortal = _loadDarkSide ? 1 : 0; } if (_vm->getGameID() == GType_WorldOfXeen) { - if (_loadDarkSide) { + if (!_loadDarkSide) { _animationInfo.load("clouds.dat"); _monsterData.load("xeen.mon"); _wallPicSprites.load("xeenpic.dat"); @@ -1050,7 +1050,7 @@ void Map::load(int mapId) { filename = "085.obj"; _mobData._objectSprites[0]._spriteId = 85; } else { - filename = Common::String::format("xeen|%03d.%cbj", + filename = Common::String::format("%03d.%cbj", _mobData._objectSprites[i]._spriteId, _mobData._objectSprites[i]._spriteId >= 100 ? '0' : 'o'); } diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 273a4b4a9d..499b451bbc 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -345,7 +345,7 @@ private: MazeData _mazeData[9]; Common::String _mazeName; SpriteResource _wallPicSprites; - bool _townPortalSide; + int _sideTownPortal; int _sidePictures; int _sideObjects; int _sideMonsters; -- cgit v1.2.3 From de1341ddb54befd64776370f988774970e5a9494 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 09:39:33 -0500 Subject: XEEN: Add special case block to Map::load --- engines/xeen/map.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 4adf356a0c..043f8c0bf6 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1044,7 +1044,9 @@ void Map::load(int mapId) { for (uint i = 0; i < _mobData._objectSprites.size(); ++i) { if (_vm->_party->_cloudsEnd && _mobData._objectSprites[i]._spriteId == 85 && mapId == 27 && isDarkCc) { - // TODO: Flags set that don't seem to be used + _mobData._objects[29]._spriteId = 0; + _mobData._objects[29]._id = 8; + _mobData._objectSprites[i]._sprites.clear(); } else if (mapId == 12 && _vm->_party->_gameFlags[43] && _mobData._objectSprites[i]._spriteId == 118 && !isDarkCc) { filename = "085.obj"; -- cgit v1.2.3 From f69fd28fe0dd4aceeb21f186101a2236f7d89740 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 10:13:32 -0500 Subject: XEEN: Fixes for hit points calculations --- engines/xeen/party.cpp | 33 +++++++++++++++++---------------- engines/xeen/party.h | 2 +- engines/xeen/resources.cpp | 6 +++--- 3 files changed, 21 insertions(+), 20 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 791a19ff4f..2822e41769 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -166,7 +166,7 @@ int Character::getAge(bool ignoreTemp) const { int Character::getMaxHP() const { int hp = BASE_HP_BY_CLASS[_class]; - hp += statBonus(getStat(ENDURANCE, false)); + hp += statBonus(getStat(ENDURANCE)); hp += RACE_HP_BONUSES[_race]; if (_skills[BODYBUILDER]) ++hp; @@ -176,10 +176,7 @@ int Character::getMaxHP() const { hp *= getCurrentLevel(); hp += itemScan(7); - if (hp < 0) - hp = 0; - - return hp; + return MAX(hp, 0); } int Character::getMaxSP() const { @@ -204,7 +201,7 @@ int Character::getMaxSP() const { for (;;) { // Get the base number of spell points - result = statBonus(getStat(attrib, false)); + result = statBonus(getStat(attrib)); result += RACE_SP_BONUSES[_race][attrib - 1]; if (_skills[skill]) @@ -240,7 +237,7 @@ int Character::getMaxSP() const { /** * Get the effective value of a given stat for the character */ -int Character::getStat(Attribute attrib, bool applyMod) const { +int Character::getStat(Attribute attrib, bool baseOnly) const { AttributePair attr; int mode = 0; @@ -277,32 +274,36 @@ int Character::getStat(Attribute attrib, bool applyMod) const { if (mode < 2) { int age = getAge(false); int ageIndex = 0; - while (AGE_RANGES[ageIndex] < age) + while (AGE_RANGES[ageIndex] <= age) ++ageIndex; attr._permanent += AGE_RANGES_ADJUST[mode][ageIndex]; } - if (applyMod) { + + attr._permanent += itemScan((int)attrib); + + if (!baseOnly) { attr._permanent += conditionMod(attrib); attr._permanent += attr._temporary; } - return (attr._permanent >= 1) ? attr._permanent : 0; + return MAX(attr._permanent, 0); } int Character::statBonus(int statValue) const { - for (int idx = 0; STAT_VALUES[idx] <= statValue; ++idx) - return STAT_BONUSES[idx]; + int idx; + for (idx = 0; STAT_VALUES[idx] <= statValue; ++idx) + ; - return 0; + return STAT_BONUSES[idx]; } bool Character::charSavingThrow(DamageType attackType) const { int v, vMax; if (attackType == DT_PHYSICAL) { - v = statBonus(getStat(LUCK, false)) + getCurrentLevel(); + v = statBonus(getStat(LUCK)) + getCurrentLevel(); vMax = v + 20; } else { switch (attackType) { @@ -378,7 +379,7 @@ bool Character::hasAward(int awardId) const { int Character::getArmorClass(bool baseOnly) const { Party &party = *Party::_vm->_party; - int result = statBonus(getStat(SPEED, false)) + itemScan(9); + int result = statBonus(getStat(SPEED)) + itemScan(9); if (!baseOnly) result += (party._blessedActive ? 1 : 0) + _ACTemp; @@ -762,7 +763,7 @@ void Party::changeTime(int numMinutes) { if (!player._conditions[DEAD] && !player._conditions[STONED] && !player._conditions[ERADICATED]) { for (int statNum = 0; statNum < TOTAL_STATS; ++statNum) { - int statVal = player.getStat((Attribute)statNum, false); + int statVal = player.getStat((Attribute)statNum); if (statVal < 1) player._conditions[DEAD] = 1; } diff --git a/engines/xeen/party.h b/engines/xeen/party.h index f56190982d..dc87e88bd8 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -146,7 +146,7 @@ public: int getMaxSP() const; - int getStat(Attribute attrib, bool applyMod) const; + int getStat(Attribute attrib, bool baseOnly = false) const; int statBonus(int statValue) const; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 993bf2f546..556544d4e4 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -508,12 +508,12 @@ const int AGE_RANGES_ADJUST[2][10] = { }; const int STAT_VALUES[24] = { - 11, 13, 15, 17, 19, 21, 25, 30, 35, 40, 50, 75, - 100, 125, 150, 175, 200, 225, 250, 65535 + 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 25, 30, 35, 40, + 50, 75, 100, 125, 150, 175, 200, 225, 250, 65535 }; const int STAT_BONUSES[24] = { - 251, 252, 253, 254, 255, 0, 1, 2, 3, 4, 5, 6, + -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20 }; -- cgit v1.2.3 From 82010fb5ef27ea622103d91c0b6bcad67366ee32 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 10:24:45 -0500 Subject: XEEN: Formatting fixes --- engines/xeen/interface_map.cpp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 2d2fddf4e0..95263c99a3 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -438,8 +438,7 @@ void InterfaceMap::draw3d(bool updateFlag) { if (_isAnimReset) { mazeObject._frame = animEntry._frame1._frames[directionIndex]; - } - else { + } else { ++mazeObject._frame; if ((int)idx == objNum && scripts._animCounter > 0 && ( objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) || @@ -457,8 +456,7 @@ void InterfaceMap::draw3d(bool updateFlag) { if (map._isOutdoors) { error("TODO: draw3d outdoors handling"); - } - else { + } else { // Default all the parts of draw struct not to be drawn by default for (int idx = 3; idx < _indoorList.size(); ++idx) _indoorList[idx]._frame = -1; @@ -478,8 +476,7 @@ void InterfaceMap::draw3d(bool updateFlag) { _indoorList[162 + idx]._frame = 0; } } - } - else if (_charsShooting) { + } else if (_charsShooting) { for (int idx = 0; idx < 96; ++idx) { if (_indoorList[162 + idx]._sprites != nullptr) { _indoorList[162 + idx]._frame = 0; @@ -522,8 +519,7 @@ void InterfaceMap::draw3d(bool updateFlag) { if (ds1._scale == 0x8000) { ds1._x /= 3; ds1._y = 60; - } - else { + } else { ds1._y = 73; } @@ -561,8 +557,7 @@ void InterfaceMap::draw3d(bool updateFlag) { _indoorList[156]._sprites = nullptr; _indoorList[157]._sprites = nullptr; monsterIndex = 1; - } - else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 0) { + } else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 0) { _indoorList[159] = _indoorList[150]; _indoorList[160] = _indoorList[151]; _indoorList[161] = _indoorList[152]; @@ -570,8 +565,7 @@ void InterfaceMap::draw3d(bool updateFlag) { _indoorList[151]._sprites = nullptr; _indoorList[150]._sprites = nullptr; monsterIndex = 2; - } - else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 0) { + } else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 0) { _indoorList[159] = _indoorList[153]; _indoorList[160] = _indoorList[154]; _indoorList[161] = _indoorList[155]; @@ -2250,6 +2244,9 @@ void InterfaceMap::setMazeBits() { } } +/** + * Set up draw structures for displaying on-screen monsters + */ void InterfaceMap::setIndoorsMonsters() { Combat &combat = *_vm->_combat; Map &map = *_vm->_map; @@ -2498,6 +2495,10 @@ void InterfaceMap::setIndoorsMonsters() { } } +/** + * Helper method for setIndoorsMonsters to set a draw structure + * with the deatils for a given monster + */ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, SpriteResource *sprites, int frame, int defaultY) { MonsterStruct &monsterData = _vm->_map->_monsterData[monster._spriteId]; @@ -2519,6 +2520,9 @@ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster drawStruct._flags = MONSTER_EFFECT_FLAGS[monster._effect2][monster._effect3]; } +/** + * Set up draw structures for displaying on-screen objects + */ void InterfaceMap::setIndoorsObjects() { Common::Point mazePos = _vm->_party->_mazePosition; Direction dir = _vm->_party->_mazeDirection; @@ -2744,6 +2748,9 @@ void InterfaceMap::setIndoorsObjects() { } } +/** + * Set up draw structures for displaying on-screen wall items + */ void InterfaceMap::setIndoorsWallPics() { Map &map = *_vm->_map; const Common::Point &mazePos = _vm->_party->_mazePosition; @@ -2978,6 +2985,9 @@ void InterfaceMap::setOutdoorsObjects() { } +/** + * Draw the contents of the current 3d view of an indoor map + */ void InterfaceMap::drawIndoors() { Map &map = *_vm->_map; int surfaceId; -- cgit v1.2.3 From c17c2aead5990d0ad5e69c0ea7c083a49b35ae96 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 12:09:16 -0500 Subject: XEEN: Implemented outdoors drawing code in draw3d --- engines/xeen/interface_map.cpp | 159 +++++++++++++++++++++++++++++++++++++---- engines/xeen/interface_map.h | 2 + engines/xeen/resources.cpp | 7 ++ engines/xeen/resources.h | 2 + 4 files changed, 158 insertions(+), 12 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 95263c99a3..42bc079797 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -413,6 +413,11 @@ void InterfaceMap::draw3d(bool updateFlag) { Screen &screen = *_vm->_screen; Scripts &scripts = *_vm->_scripts; + const int COMBAT_POS_X[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } }; + const int INDOOR_INDEXES[3] = { 157, 151, 154 }; + const int OUTDOOR_INDEXES[3] = { 119, 113, 116 }; + const int COMBAT_OFFSET_X[4] = { 8, 6, 4, 2 }; + if (screen._windows[11]._enabled) return; @@ -455,8 +460,133 @@ void InterfaceMap::draw3d(bool updateFlag) { } if (map._isOutdoors) { - error("TODO: draw3d outdoors handling"); + // Outdoors drawing + for (int idx = 0; idx < 44; ++idx) + _outdoorList[OUTDOOR_DRAWSTRCT_INDEXES[idx]]._frame = -1; + + if (_flag1) { + for (int idx = 0; idx < 8; ++idx) { + if (_outdoorList._combatImgs4[idx]._sprites) + _outdoorList._combatImgs4[idx]._frame = 0; + else if (_outdoorList._combatImgs3[idx]._sprites) + _outdoorList._combatImgs3[idx]._frame = 1; + else if (_outdoorList._combatImgs2[idx]._sprites) + _outdoorList._combatImgs2[idx]._frame = 2; + else if (_outdoorList._combatImgs1[idx]._sprites) + _outdoorList._combatImgs1[idx]._frame = 0; + } + } else if (_charsShooting) { + for (int idx = 0; idx < 8; ++idx) { + if (_outdoorList._combatImgs1[idx]._sprites) + _outdoorList._combatImgs1[idx]._frame = 0; + else if (_outdoorList._combatImgs2[idx]._sprites) + _outdoorList._combatImgs2[idx]._frame = 1; + else if (_outdoorList._combatImgs3[idx]._sprites) + _outdoorList._combatImgs3[idx]._frame = 2; + else if (_outdoorList._combatImgs4[idx]._sprites) + _outdoorList._combatImgs1[idx]._frame = 0; + } + } + + _isAnimReset = false; + int attackMon2 = combat._attackMonsters[2]; + + for (int idx = 0; idx < 3; ++idx) { + DrawStruct &ds1 = _outdoorList[OUTDOOR_INDEXES[idx] + 1]; + DrawStruct &ds2 = _outdoorList[OUTDOOR_INDEXES[idx]]; + ds1._sprites = nullptr; + ds2._sprites = nullptr; + + if (combat._charsArray1[idx]) { + int vIndex = combat._attackMonsters[1] && !attackMon2 ? 1 : 0; + combat._charsArray1[idx]--; + + if (combat._monPow[idx]) { + ds2._x = COMBAT_POS_X[idx][vIndex]; + ds2._frame = 0; + ds2._scale = combat._monsterScale[idx]; + + if (ds2._scale == 0x8000) { + ds2._x /= 3; + ds2._y = 60; + } else { + ds2._y = 73; + } + + ds2._flags = SPRFLAG_4000 | SPRFLAG_2000; + ds2._sprites = &_charPowSprites; + } + + if (combat._elemPow[idx]) { + ds1._x = COMBAT_POS_X[idx][vIndex] + COMBAT_OFFSET_X[idx]; + ds1._frame = combat._elemPow[idx]; + ds1._scale = combat._elemScale[idx]; + + if (ds1._scale == 0x8000) + ds1._x /= 3; + ds1._flags = SPRFLAG_4000 | SPRFLAG_2000; + ds1._sprites = &_charPowSprites; + } + } + } + + setOutdoorsMonsters(); + setOutdoorsObjects(); + + _outdoorList[123]._sprites = nullptr; + _outdoorList[122]._sprites = nullptr; + _outdoorList[121]._sprites = nullptr; + + int monsterIndex; + if (combat._attackMonsters[0] != -1 && map._mobData._monsters[combat._attackMonsters[0]]._frame >= 8) { + _outdoorList[121] = _outdoorList[118]; + _outdoorList[122] = _outdoorList[119]; + _outdoorList[123] = _outdoorList[120]; + _outdoorList[118]._sprites = nullptr; + _outdoorList[119]._sprites = nullptr; + _outdoorList[120]._sprites = nullptr; + monsterIndex = 1; + } else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 8) { + _outdoorList[121] = _outdoorList[112]; + _outdoorList[122] = _outdoorList[113]; + _outdoorList[123] = _outdoorList[114]; + _outdoorList[112]._sprites = nullptr; + _outdoorList[113]._sprites = nullptr; + _outdoorList[124]._sprites = nullptr; + monsterIndex = 2; + } else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 8) { + _outdoorList[121] = _outdoorList[115]; + _outdoorList[122] = _outdoorList[116]; + _outdoorList[123] = _outdoorList[117]; + _outdoorList[115]._sprites = nullptr; + _outdoorList[116]._sprites = nullptr; + _outdoorList[117]._sprites = nullptr; + monsterIndex = 3; + } + + drawOutdoors(); + + switch (monsterIndex) { + case 1: + _outdoorList[118] = _outdoorList[121]; + _outdoorList[119] = _outdoorList[122]; + _outdoorList[120] = _outdoorList[123]; + break; + case 2: + _outdoorList[112] = _outdoorList[121]; + _outdoorList[113] = _outdoorList[122]; + _outdoorList[114] = _outdoorList[123]; + break; + case 3: + _outdoorList[115] = _outdoorList[121]; + _outdoorList[116] = _outdoorList[122]; + _outdoorList[117] = _outdoorList[123]; + break; + default: + break; + } } else { + // Indoor drawing // Default all the parts of draw struct not to be drawn by default for (int idx = 3; idx < _indoorList.size(); ++idx) _indoorList[idx]._frame = -1; @@ -495,11 +625,8 @@ void InterfaceMap::draw3d(bool updateFlag) { setMazeBits(); _isAnimReset = false; - const int INDOOR_INDEXES[3] = { 157, 151, 154 }; - const int INDOOR_COMBAT_POS[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } }; - const int INDOOR_COMBAT_POS2[4] = { 8, 6, 4, 2 }; - // Double check this, since it's not being used? + // Code in the original that's not being used //MazeObject &objObject = map._mobData._objects[_objNumber - 1]; for (int idx = 0; idx < 3; ++idx) { @@ -513,7 +640,7 @@ void InterfaceMap::draw3d(bool updateFlag) { --combat._charsArray1[idx]; if (combat._monPow[idx]) { - ds1._x = INDOOR_COMBAT_POS[idx][0]; + ds1._x = COMBAT_POS_X[idx][posIndex]; ds1._frame = 0; ds1._scale = combat._monsterScale[idx]; if (ds1._scale == 0x8000) { @@ -528,7 +655,7 @@ void InterfaceMap::draw3d(bool updateFlag) { } if (combat._elemPow[idx]) { - ds2._x = INDOOR_COMBAT_POS[idx][posIndex] + INDOOR_COMBAT_POS2[idx]; + ds2._x = COMBAT_POS_X[idx][posIndex] + COMBAT_OFFSET_X[idx]; ds2._frame = combat._elemPow[idx]; ds2._scale = combat._elemScale[idx]; if (ds2._scale == 0x8000) @@ -549,7 +676,7 @@ void InterfaceMap::draw3d(bool updateFlag) { // Handle attacking monsters int monsterIndex = 0; - if (combat._attackMonsters[0] != -1 && map._mobData._monsters[combat._attackMonsters[0]]._frame >= 0) { + if (combat._attackMonsters[0] != -1 && map._mobData._monsters[combat._attackMonsters[0]]._frame >= 8) { _indoorList[159] = _indoorList[156]; _indoorList[160] = _indoorList[157]; _indoorList[161] = _indoorList[158]; @@ -557,7 +684,7 @@ void InterfaceMap::draw3d(bool updateFlag) { _indoorList[156]._sprites = nullptr; _indoorList[157]._sprites = nullptr; monsterIndex = 1; - } else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 0) { + } else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 8) { _indoorList[159] = _indoorList[150]; _indoorList[160] = _indoorList[151]; _indoorList[161] = _indoorList[152]; @@ -565,7 +692,7 @@ void InterfaceMap::draw3d(bool updateFlag) { _indoorList[151]._sprites = nullptr; _indoorList[150]._sprites = nullptr; monsterIndex = 2; - } else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 0) { + } else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 8) { _indoorList[159] = _indoorList[153]; _indoorList[160] = _indoorList[154]; _indoorList[161] = _indoorList[155]; @@ -2978,11 +3105,11 @@ void InterfaceMap::setIndoorsWallPics() { } void InterfaceMap::setOutdoorsMonsters() { - + // TODO } void InterfaceMap::setOutdoorsObjects() { - + // TODO } /** @@ -3834,6 +3961,14 @@ void InterfaceMap::drawIndoors() { _charsShooting = _isShooting; } +/** + * Draw the contents of the current 3d view of an outdoor map + */ +void InterfaceMap::drawOutdoors() { + // TODO +} + + void InterfaceMap::moveMonsters() { // TODO } diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 3ae73b76e8..4a4ff13fd8 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -166,6 +166,8 @@ public: void setOutdoorsObjects(); + void drawOutdoors(); + void drawTownAnim(int v); }; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 556544d4e4..b54779d0f4 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -550,4 +550,11 @@ const int METAL_LAC[9] = { -3, 0, -2, -1, 1, 2, 4, 6, 8 }; const int ARMOR_STRENGTHS[14] = { 0, 2, 4, 5, 6, 7, 8, 10, 4, 2, 1, 1, 1, 1 }; +const int OUTDOOR_DRAWSTRCT_INDEXES[44] = { + 37, 38, 39, 40, 41, 44, 42, 43, 47, 45, 46, + 48, 49, 52, 50, 51, 66, 67, 68, 69, 70, 71, + 72, 75, 73, 74, 87, 88, 89, 90, 91, 94, 92, + 93, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120 +}; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index b1c972069c..58ac4055b1 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -142,6 +142,8 @@ extern const int METAL_LAC[9]; extern const int ARMOR_STRENGTHS[14]; +extern const int OUTDOOR_DRAWSTRCT_INDEXES[44]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From a04daf38207bf6b7624bea04a662c38968f4e7d9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 13:49:41 -0500 Subject: XEEN: Implemented drawOutdoorsMonsters --- engines/xeen/interface_map.cpp | 250 ++++++++++++++++++++++++++++++++++++++++- engines/xeen/resources.cpp | 13 ++- engines/xeen/resources.h | 6 +- 3 files changed, 264 insertions(+), 5 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 42bc079797..9c3d7b7192 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -2379,7 +2379,6 @@ void InterfaceMap::setIndoorsMonsters() { Map &map = *_vm->_map; Common::Point mazePos = _vm->_party->_mazePosition; Direction dir = _vm->_party->_mazeDirection; - const int INDOOR_MONSTERS_Y[4] = { 2, 34, 53, 59 }; combat.clear(); for (uint monsterIdx = 0; monsterIdx < map._mobData._monsters.size(); ++monsterIdx) { @@ -3105,6 +3104,255 @@ void InterfaceMap::setIndoorsWallPics() { } void InterfaceMap::setOutdoorsMonsters() { + Combat &combat = *_vm->_combat; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Direction dir = party._mazeDirection; + Common::Point pt = party._mazePosition; + + for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) { + MazeMonster &monster = map._mobData._monsters[idx]; + + if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][2]) && + monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][2])) { + monster._isAttacking = true; + if (combat._attackMonsters[0] == -1) { + _outdoorList[118]._frame = idx; + combat._attackMonsters[0] = idx; + } else if (combat._attackMonsters[1] == -1) { + _outdoorList[112]._frame = idx; + combat._attackMonsters[1] = idx; + } else if (combat._attackMonsters[2] == -1) { + _outdoorList[115]._frame = idx; + combat._attackMonsters[2] = idx; + } + } + + if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][7]) && + monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][7])) { + monster._isAttacking = true; + if (combat._attackMonsters[3] == -1) { + _outdoorList[94]._frame = idx; + combat._attackMonsters[3] = idx; + } else if (combat._attackMonsters[4] == -1) { + _outdoorList[92]._frame = idx; + combat._attackMonsters[4] = idx; + } else if (combat._attackMonsters[5] == -1) { + _outdoorList[93]._frame = idx; + combat._attackMonsters[5] = idx; + } + } + + if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][5]) && + monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][5])) { + monster._isAttacking = true; + if (combat._attackMonsters[12] == -1) { + _outdoorList[90]._frame = idx; + combat._attackMonsters[12] = idx; + } + } + + if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][9]) && + monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][9])) { + monster._isAttacking = true; + if (combat._attackMonsters[13] == -1) { + _outdoorList[91]._frame = idx; + combat._attackMonsters[13] = idx; + } + } + + if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][14]) && + monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][14])) { + monster._isAttacking = true; + if (combat._attackMonsters[6] == -1) { + _outdoorList[75]._frame = idx; + combat._attackMonsters[6] = idx; + } else if (combat._attackMonsters[7] == -1) { + _outdoorList[73]._frame = idx; + combat._attackMonsters[7] = idx; + } else if (combat._attackMonsters[8] == -1) { + _outdoorList[74]._frame = idx; + combat._attackMonsters[8] = idx; + } + } + + if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][12]) && + monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][12])) { + monster._isAttacking = true; + if (combat._attackMonsters[14] == -1) { + _outdoorList[69]._frame = idx; + combat._attackMonsters[14] = idx; + } else if (combat._attackMonsters[20] == -1) { + _outdoorList[70]._frame = idx; + combat._attackMonsters[20] = idx; + } + } + + if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][16]) && + monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][16])) { + monster._isAttacking = true; + if (combat._attackMonsters[15] == -1) { + _outdoorList[71]._frame = idx; + combat._attackMonsters[15] = idx; + } else if (combat._attackMonsters[21] == -1) { + _outdoorList[72]._frame = idx; + combat._attackMonsters[21] = idx; + } + } + + if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][27]) && + monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][27])) { + monster._isAttacking = true; + if (combat._attackMonsters[9] == -1) { + _outdoorList[52]._frame = idx; + combat._attackMonsters[9] = idx; + } else if (combat._attackMonsters[10] == -1) { + _outdoorList[50]._frame = idx; + combat._attackMonsters[10] = idx; + } else if (combat._attackMonsters[11] == -1) { + _outdoorList[51]._frame = idx; + combat._attackMonsters[11] = idx; + } + } + + if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][25]) && + monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][25])) { + monster._isAttacking = true; + if (combat._attackMonsters[16] == -1) { + _outdoorList[44]._frame = idx; + combat._attackMonsters[16] = idx; + } else if (combat._attackMonsters[22] == -1) { + _outdoorList[42]._frame = idx; + combat._attackMonsters[22] = idx; + } else if (combat._attackMonsters[24] == -1) { + _outdoorList[43]._frame = idx; + combat._attackMonsters[24] = idx; + } + } + + if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][23]) && + monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][23])) { + monster._isAttacking = true; + if (combat._attackMonsters[18] == -1) { + _outdoorList[48]._frame = idx; + combat._attackMonsters[18] = idx; + } + } + + if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][29]) && + monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][29])) { + monster._isAttacking = true; + if (combat._attackMonsters[17] == -1) { + _outdoorList[47]._frame = idx; + combat._attackMonsters[17] = idx; + } else if (combat._attackMonsters[23] == -1) { + _outdoorList[45]._frame = idx; + combat._attackMonsters[23] = idx; + } else if (combat._attackMonsters[25] == -1) { + _outdoorList[46]._frame = idx; + combat._attackMonsters[25] = idx; + } + } + + if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][31]) && + monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][31])) { + monster._isAttacking = true; + if (combat._attackMonsters[19] == -1) { + _outdoorList[49]._frame = idx; + combat._attackMonsters[19] = idx; + } + } + } + + _outdoorList[115]._x = 58; + _outdoorList[93]._x = 25; + _outdoorList[74]._x = 9; + _outdoorList[51]._x = -1; + _outdoorList[43]._x = -26; + _outdoorList[46]._x = 23; + _outdoorList[48]._x = -58; + _outdoorList[49]._x = 40; + _outdoorList[69]._x = -65; + _outdoorList[70]._x = -85; + _outdoorList[71]._x = 49; + _outdoorList[72]._x = 65; + _outdoorList[90]._x = -112; + _outdoorList[91]._x = 98; + + if (combat._attackMonsters[1] != -1 && combat._attackMonsters[2] == -1) { + _outdoorList[118]._x = 31; + _outdoorList[112]._x = -36; + } else { + _outdoorList[118]._x = -5; + _outdoorList[112]._x = -67; + } + if (combat._attackMonsters[4] != -1 && combat._attackMonsters[5] == -1) { + _outdoorList[94]._x = 8; + _outdoorList[92]._x = -23; + } else { + _outdoorList[94]._x = -7; + _outdoorList[92]._x = -38; + } + if (combat._attackMonsters[7] != -1 && combat._attackMonsters[8] == -1) { + _outdoorList[75]._x = 0; + _outdoorList[73]._x = -16; + } else { + _outdoorList[75]._x = -8; + _outdoorList[73]._x = -24; + } + if (combat._attackMonsters[10] != -1 && combat._attackMonsters[11] == -1) { + _outdoorList[52]._x = -5; + _outdoorList[50]._x = -13; + } else { + _outdoorList[52]._x = -9; + _outdoorList[50]._x = -17; + } + if (combat._attackMonsters[22] != -1 && combat._attackMonsters[24] == -1) { + _outdoorList[44]._x = -27; + _outdoorList[42]._x = -37; + } else { + _outdoorList[44]._x = -34; + _outdoorList[42]._x = -41; + } + if (combat._attackMonsters[23] != -1 && combat._attackMonsters[25] == -1) { + _outdoorList[47]._x = 20; + _outdoorList[45]._x = -12; + } else { + _outdoorList[47]._x = 16; + _outdoorList[45]._x = -16; + } + + for (int idx = 0; idx < 26; ++idx) { + DrawStruct &ds = _outdoorList[OUTDOOR_MONSTER_INDEXES[idx]]; + + if (ds._frame != -1) { + ds._flags &= ~0xfff; + + // TODO: Double-check.. this section looks *weird* + MazeMonster &monster = map._mobData._monsters[ds._frame]; + MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + + ds._frame = monster._frame; + + if (monster._effect2) { + ds._flags = MONSTER_EFFECT_FLAGS[monster._effect2 - 1][monster._effect3]; + } + + if (monster._frame > 7) { + monster._frame -= 8; + ds._sprites = monster._attackSprites; + } else { + ds._sprites = monster._sprites; + } + + ds._y = OUTDOOR_MONSTERS_Y[idx]; + + if (monsterData._flying) { + ds._x += COMBAT_FLOAT_X[_combatFloatCounter]; + ds._y += COMBAT_FLOAT_Y[_combatFloatCounter]; + } + } + } // TODO } diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index b54779d0f4..803fea2e12 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -404,14 +404,21 @@ const int INDOOR_OBJECT_Y[2][12] = { { -65, -6, -6, -6, 36, 36, 36, 54, 54, 54, 54, 54 } }; +const int INDOOR_MONSTERS_Y[4] = { 2, 34, 53, 59 }; + const int OUTDOOR_OBJECT_X[2][12] = { { -5, -7, -112, 98, -8, -77, 61, -9, -43, 25, -74, 56 }, { -35, -35, -142, 68, -35, -95, 19, -35, -62, -24, -98, 16 } }; -const int OUTDOOR_OBJECT_Y[2][12] = { - { 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 69 }, - { 70, 71, 72, 73, 74, 75, 90, 91, 92, 93, 94, 112 } +const int OUTDOOR_MONSTER_INDEXES[26] = { + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 69, 70, + 71, 72, 73, 74, 75, 90, 91, 92, 93, 94, 112, 115, 118 +}; + +const int OUTDOOR_MONSTERS_Y[26] = { + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 53, 53, + 53, 53, 53, 53, 53, 34, 34, 34, 34, 34, 2, 2, 2 }; const int DIRECTION_ANIM_POSITIONS[4][4] = { diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 58ac4055b1..98c30f4f34 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -98,9 +98,13 @@ extern const int INDOOR_OBJECT_X[2][12]; extern const int INDOOR_OBJECT_Y[2][12]; +extern const int INDOOR_MONSTERS_Y[4]; + extern const int OUTDOOR_OBJECT_X[2][12]; -extern const int OUTDOOR_OBJECT_Y[2][12]; +extern const int OUTDOOR_MONSTER_INDEXES[26]; + +extern const int OUTDOOR_MONSTERS_Y[26]; extern const int DIRECTION_ANIM_POSITIONS[4][4]; -- cgit v1.2.3 From 409edeb1e8bb77db8cfa7b3621be41f8772fd2e1 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 14:15:24 -0500 Subject: XEEN: Implemented drawOutdoorsObjects --- engines/xeen/interface_map.cpp | 203 ++++++++++++++++++++++++++++++++++++++--- engines/xeen/resources.cpp | 2 +- engines/xeen/resources.h | 2 +- 3 files changed, 192 insertions(+), 15 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 9c3d7b7192..a699b8f638 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -2672,7 +2672,7 @@ void InterfaceMap::setIndoorsObjects() { && (mazePos.y + SCREEN_POSITIONING_Y[dir][2]) == mazeObject._position.y && _indoorList._objects0._frame == -1) { _indoorList._objects0._x = INDOOR_OBJECT_X[listOffset][0]; - _indoorList._objects0._y = INDOOR_OBJECT_Y[listOffset][0]; + _indoorList._objects0._y = MAP_OBJECT_Y[listOffset][0]; _indoorList._objects0._frame = mazeObject._frame; _indoorList._objects0._sprites = mazeObject._sprites; _indoorList._objects0._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -2686,7 +2686,7 @@ void InterfaceMap::setIndoorsObjects() { && (mazePos.y + SCREEN_POSITIONING_Y[dir][7]) == mazeObject._position.y && !_wo[27] && _indoorList._objects1._frame == -1) { _indoorList._objects1._x = INDOOR_OBJECT_X[listOffset][1]; - _indoorList._objects1._y = INDOOR_OBJECT_Y[listOffset][1]; + _indoorList._objects1._y = MAP_OBJECT_Y[listOffset][1]; _indoorList._objects1._frame = mazeObject._frame; _indoorList._objects1._sprites = mazeObject._sprites; _indoorList._objects1._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -2703,7 +2703,7 @@ void InterfaceMap::setIndoorsObjects() { } else if (_wo[23] && _wo[28]) { } else if (_indoorList._objects2._frame == -1) { _indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][2]; - _indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][2]; + _indoorList._objects2._y = MAP_OBJECT_Y[listOffset][2]; _indoorList._objects2._frame = mazeObject._frame; _indoorList._objects2._sprites = mazeObject._sprites; _indoorList._objects2._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -2721,7 +2721,7 @@ void InterfaceMap::setIndoorsObjects() { } else if (_wo[24] && _wo[29]) { } else if (_indoorList._objects3._frame == -1) { _indoorList._objects3._x = INDOOR_OBJECT_X[listOffset][3]; - _indoorList._objects3._y = INDOOR_OBJECT_Y[listOffset][3]; + _indoorList._objects3._y = MAP_OBJECT_Y[listOffset][3]; _indoorList._objects3._frame = mazeObject._frame; _indoorList._objects3._sprites = mazeObject._sprites; _indoorList._objects3._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -2735,7 +2735,7 @@ void InterfaceMap::setIndoorsObjects() { && (mazePos.y + SCREEN_POSITIONING_Y[dir][14]) == mazeObject._position.y) { if (!_wo[22] && !_wo[27] && _indoorList._objects4._frame == -1) { _indoorList._objects4._x = INDOOR_OBJECT_X[listOffset][4]; - _indoorList._objects4._y = INDOOR_OBJECT_Y[listOffset][4]; + _indoorList._objects4._y = MAP_OBJECT_Y[listOffset][4]; _indoorList._objects4._frame = mazeObject._frame; _indoorList._objects4._sprites = mazeObject._sprites; _indoorList._objects4._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -2754,7 +2754,7 @@ void InterfaceMap::setIndoorsObjects() { } else if (_wo[20] && _wo[17]) { } else if (_indoorList._objects5._frame == -1) { _indoorList._objects5._x = INDOOR_OBJECT_X[listOffset][5]; - _indoorList._objects5._y = INDOOR_OBJECT_Y[listOffset][5]; + _indoorList._objects5._y = MAP_OBJECT_Y[listOffset][5]; _indoorList._objects5._frame = mazeObject._frame; _indoorList._objects5._sprites = mazeObject._sprites; _indoorList._objects5._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -2773,7 +2773,7 @@ void InterfaceMap::setIndoorsObjects() { } else if (_wo[21] && _wo[19]) { } else if (_indoorList._objects6._frame == -1) { _indoorList._objects6._x = INDOOR_OBJECT_X[listOffset][6]; - _indoorList._objects6._y = INDOOR_OBJECT_Y[listOffset][6]; + _indoorList._objects6._y = MAP_OBJECT_Y[listOffset][6]; _indoorList._objects6._frame = mazeObject._frame; _indoorList._objects6._sprites = mazeObject._sprites; _indoorList._objects6._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -2787,7 +2787,7 @@ void InterfaceMap::setIndoorsObjects() { && (mazePos.y + SCREEN_POSITIONING_Y[dir][27]) == mazeObject._position.y) { if (!_wo[27] && !_wo[22] && !_wo[15] && _indoorList._objects7._frame == -1) { _indoorList._objects7._x = INDOOR_OBJECT_X[listOffset][7]; - _indoorList._objects7._y = INDOOR_OBJECT_Y[listOffset][7]; + _indoorList._objects7._y = MAP_OBJECT_Y[listOffset][7]; _indoorList._objects7._frame = mazeObject._frame; _indoorList._objects7._sprites = mazeObject._sprites; _indoorList._objects7._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -2806,7 +2806,7 @@ void InterfaceMap::setIndoorsObjects() { } else if (_wo[17] && _wo[7]) { } else if (_indoorList._objects8._frame == -1) { _indoorList._objects8._x = INDOOR_OBJECT_X[listOffset][8]; - _indoorList._objects8._y = INDOOR_OBJECT_Y[listOffset][8]; + _indoorList._objects8._y = MAP_OBJECT_Y[listOffset][8]; _indoorList._objects8._frame = mazeObject._frame; _indoorList._objects8._sprites = mazeObject._sprites; _indoorList._objects8._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -2825,7 +2825,7 @@ void InterfaceMap::setIndoorsObjects() { } else if (_wo[23] && _wo[17]) { } else if (!_wo[12] && !_wo[8] && _indoorList._objects9._frame == -1) { _indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][9]; - _indoorList._objects9._y = INDOOR_OBJECT_Y[listOffset][9]; + _indoorList._objects9._y = MAP_OBJECT_Y[listOffset][9]; _indoorList._objects9._frame = mazeObject._frame; _indoorList._objects9._sprites = mazeObject._sprites; _indoorList._objects9._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -2844,7 +2844,7 @@ void InterfaceMap::setIndoorsObjects() { } else if (_wo[19] && _wo[9]) { } else if (_indoorList._objects10._frame == -1) { _indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][10]; - _indoorList._objects10._y = INDOOR_OBJECT_Y[listOffset][10]; + _indoorList._objects10._y = MAP_OBJECT_Y[listOffset][10]; _indoorList._objects10._frame = mazeObject._frame; _indoorList._objects10._sprites = mazeObject._sprites; _indoorList._objects10._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -2863,7 +2863,7 @@ void InterfaceMap::setIndoorsObjects() { } else if (_wo[24] && _wo[19]) { } else if (!_wo[14] && !_wo[10] && _indoorList._objects11._frame == -1) { _indoorList._objects11._x = INDOOR_OBJECT_X[listOffset][11]; - _indoorList._objects11._y = INDOOR_OBJECT_Y[listOffset][11]; + _indoorList._objects11._y = MAP_OBJECT_Y[listOffset][11]; _indoorList._objects11._frame = mazeObject._frame; _indoorList._objects11._sprites = mazeObject._sprites; _indoorList._objects11._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -3103,6 +3103,9 @@ void InterfaceMap::setIndoorsWallPics() { } } +/** + * Set up the draw structures for displaying monsters on outdoor maps + */ void InterfaceMap::setOutdoorsMonsters() { Combat &combat = *_vm->_combat; Map &map = *_vm->_map; @@ -3356,8 +3359,182 @@ void InterfaceMap::setOutdoorsMonsters() { // TODO } +/** + * Set up the draw structures for displaying objects on outdoor maps + */ void InterfaceMap::setOutdoorsObjects() { - // TODO + Map &map = *_vm->_map; + Party &party = *_vm->_party; + const Common::Point &pt = party._mazePosition; + Direction dir = party._mazeDirection; + int posIndex; + + for (uint idx = 0; idx < map._mobData._objects.size(); ++idx) { + MazeObject &obj = map._mobData._objects[idx]; + + if (_vm->_files->_isDarkCc) { + posIndex = obj._spriteId == 47 ? 1 : 0; + } else { + posIndex = obj._spriteId == 113 ? 1 : 0; + } + + if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][2]) && + obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][2]) && + _outdoorList[111]._frame == -1) { + DrawStruct &ds = _outdoorList[111]; + ds._x = OUTDOOR_OBJECT_X[posIndex][0]; + ds._y = MAP_OBJECT_Y[posIndex][0]; + ds._sprites = obj._sprites; + + ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (obj._flipped) + ds._flags |= SPRFLAG_HORIZ_FLIPPED; + _objNumber = idx; + } + + if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][7]) && + obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][7]) && + _outdoorList[87]._frame == -1) { + DrawStruct &ds = _outdoorList[87]; + ds._x = OUTDOOR_OBJECT_X[posIndex][1]; + ds._y = MAP_OBJECT_Y[posIndex][1]; + ds._sprites = obj._sprites; + + ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (obj._flipped) + ds._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][5]) && + obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][5]) && + _outdoorList[88]._frame == -1) { + DrawStruct &ds = _outdoorList[88]; + ds._x = OUTDOOR_OBJECT_X[posIndex][2]; + ds._y = MAP_OBJECT_Y[posIndex][2]; + ds._sprites = obj._sprites; + + ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (obj._flipped) + ds._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][9]) && + obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][9]) && + _outdoorList[89]._frame == -1) { + DrawStruct &ds = _outdoorList[89]; + ds._x = OUTDOOR_OBJECT_X[posIndex][3]; + ds._y = MAP_OBJECT_Y[posIndex][3]; + ds._sprites = obj._sprites; + + ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (obj._flipped) + ds._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][14]) && + obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][14]) && + _outdoorList[66]._frame == -1) { + DrawStruct &ds = _outdoorList[66]; + ds._x = OUTDOOR_OBJECT_X[posIndex][4]; + ds._y = MAP_OBJECT_Y[posIndex][4]; + ds._sprites = obj._sprites; + + ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (obj._flipped) + ds._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][12]) && + obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][12]) && + _outdoorList[67]._frame == -1) { + DrawStruct &ds = _outdoorList[67]; + ds._x = OUTDOOR_OBJECT_X[posIndex][5]; + ds._y = MAP_OBJECT_Y[posIndex][5]; + ds._sprites = obj._sprites; + + ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (obj._flipped) + ds._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][16]) && + obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][16]) && + _outdoorList[68]._frame == -1) { + DrawStruct &ds = _outdoorList[68]; + ds._x = OUTDOOR_OBJECT_X[posIndex][6]; + ds._y = MAP_OBJECT_Y[posIndex][6]; + ds._sprites = obj._sprites; + + ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (obj._flipped) + ds._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][27]) && + obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][27]) && + _outdoorList[37]._frame == -1) { + DrawStruct &ds = _outdoorList[37]; + ds._x = OUTDOOR_OBJECT_X[posIndex][7]; + ds._y = MAP_OBJECT_Y[posIndex][7]; + ds._sprites = obj._sprites; + + ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (obj._flipped) + ds._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][25]) && + obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][25]) && + _outdoorList[38]._frame == -1) { + DrawStruct &ds = _outdoorList[38]; + ds._x = OUTDOOR_OBJECT_X[posIndex][8]; + ds._y = MAP_OBJECT_Y[posIndex][8]; + ds._sprites = obj._sprites; + + ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (obj._flipped) + ds._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][23]) && + obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][23]) && + _outdoorList[40]._frame == -1) { + DrawStruct &ds = _outdoorList[40]; + ds._x = OUTDOOR_OBJECT_X[posIndex][10]; + ds._y = MAP_OBJECT_Y[posIndex][10]; + ds._sprites = obj._sprites; + + ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (obj._flipped) + ds._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][29]) && + obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][29]) && + _outdoorList[39]._frame == -1) { + DrawStruct &ds = _outdoorList[39]; + ds._x = OUTDOOR_OBJECT_X[posIndex][9]; + ds._y = MAP_OBJECT_Y[posIndex][9]; + ds._sprites = obj._sprites; + + ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (obj._flipped) + ds._flags |= SPRFLAG_HORIZ_FLIPPED; + } + + if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][31]) && + obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][31]) && + _outdoorList[41]._frame == -1) { + DrawStruct &ds = _outdoorList[41]; + ds._x = OUTDOOR_OBJECT_X[posIndex][11]; + ds._y = MAP_OBJECT_Y[posIndex][11]; + ds._sprites = obj._sprites; + + ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; + if (obj._flipped) + ds._flags |= SPRFLAG_HORIZ_FLIPPED; + } + } } /** diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 803fea2e12..26c33cad11 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -399,7 +399,7 @@ const int INDOOR_OBJECT_X[2][12] = { { -35, -35, -142, 68, -35, -95, 19, -35, -62, -14, -98, 16 } }; -const int INDOOR_OBJECT_Y[2][12] = { +const int MAP_OBJECT_Y[2][12] = { { 2, 25, 25, 25, 50, 50, 50, 58, 58, 58, 58, 58 }, { -65, -6, -6, -6, 36, 36, 36, 54, 54, 54, 54, 54 } }; diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 98c30f4f34..2e77e95dbb 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -96,7 +96,7 @@ extern const int8 SCREEN_POSITIONING_Y[4][48]; extern const int INDOOR_OBJECT_X[2][12]; -extern const int INDOOR_OBJECT_Y[2][12]; +extern const int MAP_OBJECT_Y[2][12]; extern const int INDOOR_MONSTERS_Y[4]; -- cgit v1.2.3 From 177f47a5355fdbe6e45b51328274db02baace79b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 14:48:00 -0500 Subject: XEEN: Implement drawOutdoors --- engines/xeen/interface_map.cpp | 73 +++++++++++++++++++++++++++++++++++++++--- engines/xeen/interface_map.h | 3 +- engines/xeen/map.cpp | 2 +- 3 files changed, 72 insertions(+), 6 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index a699b8f638..04f7355603 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -27,9 +27,9 @@ namespace Xeen { -OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]), - _combatImgs1(&_data[124]), _combatImgs2(&_data[95]), - _combatImgs3(&_data[76]), _combatImgs4(&_data[53]) { +OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]), + _groundSprite(_data[2]), _combatImgs1(&_data[124]), _combatImgs2(&_data[95]), + _combatImgs3(&_data[76]), _combatImgs4(&_data[53]), _groundTiles(&_data[3]) { _data[0] = DrawStruct(0, 8, 8); _data[1] = DrawStruct(1, 8, 25); _data[2] = DrawStruct(0, 8, 67); @@ -4390,7 +4390,72 @@ void InterfaceMap::drawIndoors() { * Draw the contents of the current 3d view of an outdoor map */ void InterfaceMap::drawOutdoors() { - // TODO + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + int surfaceId; + + // Draw any surface tiles on top of the default ground + for (int cellIndex = 0; cellIndex < 25; ++cellIndex) { + map.getCell(cellIndex == 24 ? 2 : DRAW_NUMBERS[cellIndex]); + + DrawStruct &drawStruct = _indoorList._groundTiles[cellIndex]; + SpriteResource &sprites = map._surfaceSprites[map._currentSurfaceId]; + drawStruct._sprites = sprites.empty() ? (SpriteResource *)nullptr : &sprites; + + surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; + if (surfaceId == SURFTYPE_DWATER || surfaceId == SURFTYPE_LAVA) { + drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWater ? 1 : 0]; + drawStruct._flags = _flipWater ? SPRFLAG_HORIZ_FLIPPED : 0; + } else { + drawStruct._frame = DRAW_FRAMES[cellIndex][_flipGround ? 1 : 0]; + drawStruct._flags = _flipGround ? SPRFLAG_HORIZ_FLIPPED : 0; + } + } + + party.handleLight(); + + // Set up terrain draw entries + const int TERRAIN_INDEXES1[9] = { 44, 36, 37, 38, 45, 43, 42, 41, 39 }; + const int TERRAIN_INDEXES2[5] = { 22, 24, 31, 29, 26 }; + const int TERRAIN_INDEXES3[3] = { 11, 16, 13 }; + const int TERRAIN_INDEXES4[5] = { 5, 9, 7, 0, 4 }; + + for (int idx = 0; idx < 9; ++idx) { + map.getCell(TERRAIN_INDEXES1[idx]); + _outdoorList[36 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data]; + } + for (int idx = 0; idx < 5; ++idx) { + map.getCell(TERRAIN_INDEXES2[idx]); + _outdoorList[61 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data]; + } + for (int idx = 0; idx < 3; ++idx) { + map.getCell(TERRAIN_INDEXES3[idx]); + _outdoorList[84 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data]; + } + for (int idx = 0; idx < 5; ++idx) { + map.getCell(TERRAIN_INDEXES4[idx]); + _outdoorList[103 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data]; + } + + map.getCell(1); + _outdoorList[108]._sprites = &map._wallSprites._surfaces[map._currentWall._data]; + _outdoorList[109]._sprites = &map._wallSprites._surfaces[map._currentWall._data]; + _outdoorList[110]._sprites = &map._wallSprites._surfaces[map._currentWall._data]; + _outdoorList._sky1._flags = _outdoorList._sky2._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0; + _outdoorList._groundSprite._flags = _flipWater ? SPRFLAG_HORIZ_FLIPPED : 0; + + // Finally render the outdoor scene + screen._windows[3].drawList(&_outdoorList[0], _outdoorList.size()); + + // Check for any character shooting + _isShooting = false; + for (int i = 0; i < _vm->_party->_partyCount; ++i) { + if (_vm->_combat->_shooting[i]) + _isShooting = true; + } + + _charsShooting = _isShooting; } diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 4a4ff13fd8..3ee2c430e9 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -34,8 +34,9 @@ class XeenEngine; class OutdoorDrawList { public: DrawStruct _data[132]; - DrawStruct &_skySprite; + DrawStruct &_sky1, &_sky2; DrawStruct &_groundSprite; + DrawStruct * const _groundTiles; DrawStruct * const _combatImgs1; DrawStruct * const _combatImgs2; DrawStruct * const _combatImgs3; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 043f8c0bf6..ae38b77ed6 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1088,7 +1088,7 @@ void Map::load(int mapId) { _groundSprites.load("water.out"); _tileSprites.load("outdoor.til"); - outdoorList._skySprite._sprites = &_skySprites[0]; + outdoorList._sky2._sprites = &_skySprites[0]; outdoorList._groundSprite._sprites = &_groundSprites; for (int i = 0; i < TOTAL_SURFACES; ++i) { -- cgit v1.2.3 From 339dfcb2cc9fde227abc15ad9b298f7b16194785 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 15:14:57 -0500 Subject: XEEN: Restrict drawing in windows to drawing within their bounds --- engines/xeen/screen.cpp | 11 +++-------- engines/xeen/sprites.cpp | 7 ++++--- engines/xeen/sprites.h | 2 +- 3 files changed, 8 insertions(+), 12 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 42182cc7fe..16e4955cde 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -38,7 +38,7 @@ Window::Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border, _vm(vm), _enabled(false), _a(a), _border(border), _xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) { setBounds(bounds); - create(_vm->_screen, Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + create(_vm->_screen, bounds); } void Window::setBounds(const Common::Rect &r) { @@ -167,17 +167,12 @@ void Window::writeString(const Common::String &s) { } void Window::drawList(DrawStruct *items, int count) { - Screen &screen = *_vm->_screen; - for (int i = 0; i < count; ++i, ++items) { if (items->_frame == -1 || items->_scale == -1 || items->_sprites == nullptr) continue; - - Common::Rect bounds = _innerBounds; - bounds.translate(items->_x, items->_y); - + // TODO: There are two sprite calls in this method. Figure out why - items->_sprites->draw(screen, items->_frame, + items->_sprites->draw(*this, items->_frame, Common::Point(items->_x, items->_y), items->_flags, items->_scale); } } diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 62074ed565..5adc0e53e2 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -104,9 +104,10 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0; int xInc = flipped ? -1 : 1; - if (dest.w < (xOffset + width) || dest.h < (yOffset + height)) - dest.create(xOffset + width, yOffset + height); - + if (flags & SPRFLAG_RESIZE) { + if (dest.w < (xOffset + width) || dest.h < (yOffset + height)) + dest.create(xOffset + width, yOffset + height); + } // The pattern steps used in the pattern command const int patternSteps[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 }; diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index d1a801e6ca..15a3b7ca87 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -34,7 +34,7 @@ namespace Xeen { class XeenEngine; enum SpriteFlags { SPRFLAG_2000 = 0x2000, SPRFLAG_4000 = 0x4000, - SPRFLAG_HORIZ_FLIPPED = 0x8000 }; + SPRFLAG_HORIZ_FLIPPED = 0x8000, SPRFLAG_RESIZE = 0x10000 }; class SpriteResource { private: -- cgit v1.2.3 From c01120aedd2eb32f15f48b780dddcccc3189acea Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 15:29:02 -0500 Subject: XEEN: Extra comments to sprite resource class --- engines/xeen/sprites.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'engines/xeen') diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 5adc0e53e2..7bffa68907 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -43,6 +43,9 @@ SpriteResource::~SpriteResource() { clear(); } +/** + * Copy operator for duplicating a sprite resource + */ SpriteResource &SpriteResource::operator=(const SpriteResource &src) { delete[] _data; _index.clear(); @@ -58,16 +61,25 @@ SpriteResource &SpriteResource::operator=(const SpriteResource &src) { return *this; } +/** + * Load a sprite resource from a given file + */ void SpriteResource::load(const Common::String &filename) { File f(filename); load(f); } +/** + * Load a sprite resource from a given file and archive + */ void SpriteResource::load(const Common::String &filename, Common::Archive &archive) { File f(filename, archive); load(f); } +/** + * Load a sprite resource from a stream + */ void SpriteResource::load(Common::SeekableReadStream &f) { // Read in a copy of the file _filesize = f.size(); @@ -86,12 +98,18 @@ void SpriteResource::load(Common::SeekableReadStream &f) { } } +/** + * Clears the sprite resource + */ void SpriteResource::clear() { delete[] _data; _data = nullptr; _filesize = 0; } +/** + * Draws a frame using data at a specific offset in the sprite resource + */ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, int flags) const { // Get cell header Common::MemoryReadStream f(_data, _filesize); @@ -229,8 +247,12 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi dest.addDirtyRect(r); } +/** + * Draw the sprite onto the given surface + */ void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, int flags, int scale) const { + assert(scale != 0x8000); // TODO: TO test when I find scale value used if (scale == 0) { drawOffset(dest, _index[frame]._offset1, destPos, flags); @@ -261,6 +283,9 @@ void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPo } } +/** + * Draw the sprite onto the given surface + */ void SpriteResource::draw(XSurface &dest, int frame) const { draw(dest, frame, Common::Point()); } -- cgit v1.2.3 From 41f7664fa854d49d20935b2a0db61fab9e46af41 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 16:10:45 -0500 Subject: XEEN: Implemented cmdIf opcode --- engines/xeen/scripts.cpp | 47 +++++++++++++++++++++++++++++++++++++++-------- engines/xeen/scripts.h | 1 - 2 files changed, 39 insertions(+), 9 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 10ba972d8d..e63cd7b67d 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -132,8 +132,6 @@ void Scripts::checkEvents() { (_currentPos.x | _currentPos.y) && event._line == _lineNum) { if (event._direction == party._mazeDirection || event._direction == DIR_ALL) { _vm->_mode = MODE_9; - _paramText = event._parameters.size() == 0 ? "" : - map._events._text[event._parameters[0]]; doOpcode(event); break; } else { @@ -197,7 +195,8 @@ void Scripts::doOpcode(MazeEvent &event) { */ void Scripts::cmdDisplay1(Common::Array<byte> ¶ms) { Screen &screen = *_vm->_screen; - Common::String msg = Common::String::format("\r\x03""c%s", _paramText.c_str()); + Common::String paramText = _vm->_map->_events._text[_event->_parameters[0]]; + Common::String msg = Common::String::format("\r\x03""c%s", paramText.c_str()); screen._windows[12].close(); if (screen._windows[38]._enabled) @@ -214,8 +213,10 @@ void Scripts::cmdDisplay1(Common::Array<byte> ¶ms) { */ void Scripts::cmdDoorTextSml(Common::Array<byte> ¶ms) { Interface &intf = *_vm->_interface; + + Common::String paramText = _vm->_map->_events._text[_event->_parameters[0]]; intf._screenText = Common::String::format("\x02\f""08\x03""c\t116\v025%s\x03""l\fd""\x01", - _paramText.c_str()); + paramText.c_str()); intf._upDoorText = true; intf.draw3d(true); @@ -228,8 +229,10 @@ void Scripts::cmdDoorTextSml(Common::Array<byte> ¶ms) { */ void Scripts::cmdDoorTextLrg(Common::Array<byte> ¶ms) { Interface &intf = *_vm->_interface; + + Common::String paramText = _vm->_map->_events._text[_event->_parameters[0]]; intf._screenText = Common::String::format("\f04\x03""c\t116\v030%s\x03""l\fd", - _paramText.c_str()); + paramText.c_str()); intf._upDoorText = true; intf.draw3d(true); @@ -242,8 +245,10 @@ void Scripts::cmdDoorTextLrg(Common::Array<byte> ¶ms) { */ void Scripts::cmdSignText(Common::Array<byte> ¶ms) { Interface &intf = *_vm->_interface; + + Common::String paramText = _vm->_map->_events._text[_event->_parameters[0]]; intf._screenText = Common::String::format("\f08\x03""c\t120\v088%s\x03""l\fd", - _paramText.c_str()); + paramText.c_str()); intf._upDoorText = true; intf.draw3d(true); @@ -273,21 +278,47 @@ void Scripts::cmdTeleport(Common::Array<byte> ¶ms) { * Do a conditional check */ void Scripts::cmdIf(Common::Array<byte> ¶ms) { + Party &party = *_vm->_party; + uint32 mask; + int newLineNum; + switch (params[0]) { case 16: case 34: case 100: - // TODO + mask = (params[4] << 24) | (params[3] << 16) | (params[2] << 8) | params[1]; + newLineNum = params[5]; break; case 25: case 35: case 101: case 106: - // TODO + mask = (params[2] << 8) | params[1]; + newLineNum = params[3]; break; default: + mask = params[1]; + newLineNum = params[2]; break; } + + bool result; + if ((_charIndex != 0 && _charIndex != 8) || params[0] == 44) { + result = ifProc(params[0], mask, _event->_opcode - 8, _charIndex); + } else { + result = false; + for (int idx = 0; idx < party._partyCount && !result; ++idx) { + if (_charIndex == 0 || (_charIndex == 8 && idx != _v2)) { + result = ifProc(params[0], mask, _event->_opcode - 8, idx); + } + } + } + + if (result) + _lineNum = newLineNum - 1; + + _var4F = true; + cmdNoAction(params); } /** diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index fb415cac8d..9725825513 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -138,7 +138,6 @@ private: int _v2; int _var4F; int _nEdamageType; - Common::String _paramText; MazeEvent *_event; Common::Point _currentPos; Common::Stack<StackEntry> _stack; -- cgit v1.2.3 From f742dc8d33abda26e47ebd4c73aa8b901e69d608 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 17:33:47 -0500 Subject: XEEN: Fixes to ifProc --- engines/xeen/files.cpp | 2 +- engines/xeen/scripts.cpp | 21 +++++++++------------ 2 files changed, 10 insertions(+), 13 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index 0c3402f00d..50949b7696 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -200,7 +200,7 @@ FileManager::FileManager(XeenEngine *vm) { Common::File f; int sideNum = 0; - _isDarkCc = vm->getGameID() != GType_Clouds; + _isDarkCc = vm->getGameID() == GType_DarkSide; _sideArchives[0] = _sideArchives[1] = nullptr; if (vm->getGameID() != GType_DarkSide) { diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index e63cd7b67d..6df53450d6 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -116,7 +116,7 @@ void Scripts::checkEvents() { _nEdamageType = 0; // int var40 = -1; - while (_lineNum >= 0) { + while (!_vm->shouldQuit() && _lineNum >= 0) { // Break out of the events if there's an attacking monster if (combat._attackMonsters[0] != -1) { _eventSkipped = true; @@ -140,9 +140,9 @@ void Scripts::checkEvents() { } } if (eventIndex == map._events.size()) - break; + _lineNum = -1; } - } while (0); + } while (!_vm->shouldQuit() && _lineNum != -1); // TODO } @@ -304,7 +304,7 @@ void Scripts::cmdIf(Common::Array<byte> ¶ms) { bool result; if ((_charIndex != 0 && _charIndex != 8) || params[0] == 44) { - result = ifProc(params[0], mask, _event->_opcode - 8, _charIndex); + result = ifProc(params[0], mask, _event->_opcode - 8, _charIndex - 1); } else { result = false; for (int idx = 0; idx < party._partyCount && !result; ++idx) { @@ -826,8 +826,7 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { if (_vm->_files->_isDarkCc) mask += 0x100; assert(mask < 0x200); - if (party._gameFlags[mask]) - v = mask; + v = party._gameFlags[mask] ? mask : 0xffffffff; break; case 21: // Scans inventories for given item number @@ -1063,8 +1062,7 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { break; case 99: // Party skills check - if (party.checkSkill((Skill)mask)) - v = mask; + v = party.checkSkill((Skill)mask) ? mask : 0xffffffff; break; case 102: // Thievery skill @@ -1072,13 +1070,12 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { break; case 103: // Get value of world flag - if (party._worldFlags[mask]) - v = mask; + v = party._worldFlags[mask] ? mask : 0xffffffff; break; case 104: // Get value of quest flag - if (party._quests[mask + (_vm->_files->_isDarkCc ? 30 : 0)]) - v = mask; + v = party._quests[mask + (_vm->_files->_isDarkCc ? 30 : 0)] ? + mask : 0xffffffff; break; case 105: // Test number of Megacredits in party. Only used by King's Engineer in Castle Burlock -- cgit v1.2.3 From 0d8d66cb82c4b6236af4b05e36f5a69461597580 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 18:31:54 -0500 Subject: XEEN: Fix center aligning text in writeString --- engines/xeen/font.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp index aee05f9066..1668ef5ae8 100644 --- a/engines/xeen/font.cpp +++ b/engines/xeen/font.cpp @@ -113,8 +113,10 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R } } else { // Found word break, find end of previous word - while (displayEnd > _displayString && (*displayEnd & 0x7f) == ' ') - --displayEnd; + while (endP > _displayString && (*endP & 0x7f) == ' ') + --endP; + + displayEnd = endP; } } @@ -123,9 +125,12 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R // Figure out the width of the selected portion of the string int totalWidth = 0; while (!getNextCharWidth(totalWidth)) { - if (_displayString > displayEnd && *displayEnd == ' ') { - // Don't include any ending space as part of the total - totalWidth -= _fontReduced ? 4 : 5; + if (_displayString > displayEnd) { + if (*displayEnd == ' ') { + // Don't include any ending space as part of the total + totalWidth -= _fontReduced ? 4 : 5; + } + break; } } -- cgit v1.2.3 From fe6b580ff11e3ee7b518e478f20a5a7423afb425 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 19:38:58 -0500 Subject: XEEN: Implement cmdCheckProtection and cmdAlterEvent opcodes --- engines/xeen/scripts.cpp | 38 +++++++++++++++++++++++++++++++++----- engines/xeen/scripts.h | 4 +++- 2 files changed, 36 insertions(+), 6 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 6df53450d6..5abd63a77e 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -178,7 +178,7 @@ void Scripts::doOpcode(MazeEvent &event) { &Scripts::cmdAlterHed, &Scripts::cmdDisplayStat, &Scripts::cmdTakeOrGive, &Scripts::cmdSeatTextSml, &Scripts::cmdPlayEventVoc, &Scripts::cmdDisplayBottom, &Scripts::cmdIfMapFlag, &Scripts::cmdSelRndChar, &Scripts::cmdGiveEnchanted, - &Scripts::cmdItemType, &Scripts::cmdMakeNothingHere, &Scripts::cmdNoAction2, + &Scripts::cmdItemType, &Scripts::cmdMakeNothingHere, &Scripts::cmdCheckProtection, &Scripts::cmdChooseNumeric, &Scripts::cmdDisplayBottomTwoLines, &Scripts::cmdDisplayLarge, &Scripts::cmdExchObj, &Scripts::cmdFallToMap, &Scripts::cmdDisplayMain, &Scripts::cmdGoto, &Scripts::cmdConfirmWord, @@ -534,7 +534,25 @@ void Scripts::cmdJumpRnd(Common::Array<byte> ¶ms) { cmdNoAction(params); } -void Scripts::cmdAlterEvent(Common::Array<byte> ¶ms) { error("TODO"); } +/** + * Alter an existing event + */ +void Scripts::cmdAlterEvent(Common::Array<byte> ¶ms) { + Map &map = *_vm->_map; + Party &party = *_vm->_party; + + for (uint idx = 0; idx < map._events.size(); ++idx) { + MazeEvent &evt = map._events[idx]; + if (evt._position == party._mazePosition && + (evt._direction == DIR_ALL || evt._direction == party._mazeDirection) && + evt._line == params[0]) { + evt._opcode = (Opcode)params[1]; + } + } + + _var4F = true; + cmdNoAction(params); +} /** * Stores the current location and line for later resuming, and set up to execute @@ -607,7 +625,13 @@ void Scripts::cmdMakeNothingHere(Common::Array<byte> ¶ms) { cmdExit(params); } -void Scripts::cmdNoAction2(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdCheckProtection(Common::Array<byte> ¶ms) { + if (copyProtectionCheck()) + cmdNoAction(params); + else + cmdExit(params); +} + void Scripts::cmdChooseNumeric(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdDisplayLarge(Common::Array<byte> ¶ms) { error("TODO"); } @@ -907,8 +931,7 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { break; case 44: v = YesNo::show(_vm, mask, 0); - if (!mask && v) - v = 0; + v = (!v && !mask) ? 2 : mask; break; case 45: // Might base (before bonus) @@ -1101,4 +1124,9 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { } } +bool Scripts::copyProtectionCheck() { + // Currentl not implemented + return true; +} + } // End of namespace Xeen diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 9725825513..66dcb9b70b 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -183,7 +183,7 @@ private: void cmdGiveEnchanted(Common::Array<byte> ¶ms); void cmdItemType(Common::Array<byte> ¶ms); void cmdMakeNothingHere(Common::Array<byte> ¶ms); - void cmdNoAction2(Common::Array<byte> ¶ms); + void cmdCheckProtection(Common::Array<byte> ¶ms); void cmdChooseNumeric(Common::Array<byte> ¶ms); void cmdDisplayBottomTwoLines(Common::Array<byte> ¶ms); void cmdDisplayLarge(Common::Array<byte> ¶ms); @@ -208,6 +208,8 @@ private: void doEnding(const Common::String &endStr, int v2); bool ifProc(int action, uint32 mask, int mode, int charIndex); + + bool copyProtectionCheck(); public: int _animCounter; bool _eventSkipped; -- cgit v1.2.3 From 2a9c00cb963b00f8255e95684d78dfe01c943fc5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 22:15:57 -0500 Subject: XEEN: Fix to cmdSpawn, and implemented cmdSetValue --- engines/xeen/party.cpp | 209 ++++++++++++++++++++++++++++++++++++++++++++++- engines/xeen/party.h | 2 + engines/xeen/scripts.cpp | 42 +++++++++- engines/xeen/scripts.h | 2 +- 4 files changed, 252 insertions(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 2822e41769..388b8de261 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -182,7 +182,7 @@ int Character::getMaxHP() const { int Character::getMaxSP() const { int result = 0; bool flag = false; - int amount; + int amount = 0; Attribute attrib; Skill skill; @@ -550,6 +550,213 @@ int Character::conditionMod(Attribute attrib) const { return v[attrib]; } +void Character::setValue(int id, uint value) { + Party &party = *Party::_vm->_party; + Scripts &scripts = *Party::_vm->_scripts; + + switch (id) { + case 3: + // Set character sex + _sex = (Sex)value; + break; + case 4: + // Set race + _race = (Race)value; + break; + case 5: + // Set class + _class = (CharacterClass)value; + break; + case 8: + // Set the current Hp + _currentHp = value; + break; + case 9: + // Set the current Sp + _currentSp = value; + break; + case 10: + case 77: + // Set temporary armor class + _ACTemp = value; + break; + case 11: + // Set temporary level + _level._temporary = value; + break; + case 12: + // Set the character's temporary age + _tempAge = value; + break; + case 16: + // Set character experience + _experience = value; + break; + case 17: + // Set party poison resistence + party._poisonResistence = value; + break; + case 18: + // Set condition + if (value == 16) { + // Clear all the conditions + Common::fill(&_conditions[CURSED], &_conditions[NO_CONDITION], false); + } else if (value == 6) { + _conditions[value] = 1; + } else { + ++_conditions[value]; + } + + if (value >= DEAD && value <= ERADICATED && _currentHp > 0) + _currentHp = 0; + break; + case 25: + // Set time of day in minutes (0-1440) + party._minutes = value; + break; + case 34: + // Set party gold + party._gold = value; + break; + case 35: + // Set party gems + party._gems = value; + break; + case 37: + _might._temporary = value; + break; + case 38: + _intellect._temporary = value; + break; + case 39: + _personality._temporary = value; + break; + case 40: + _endurance._temporary = value; + break; + case 41: + _speed._temporary = value; + break; + case 42: + _accuracy._temporary = value; + break; + case 43: + _luck._temporary = value; + break; + case 45: + _might._permanent = value; + break; + case 46: + _intellect._permanent = value; + break; + case 47: + _personality._permanent = value; + break; + case 48: + _endurance._permanent = value; + break; + case 49: + _speed._permanent = value; + break; + case 50: + _accuracy._permanent = value; + break; + case 51: + _luck._permanent = value; + break; + case 52: + _fireResistence._permanent = value; + break; + case 53: + _electricityResistence._permanent = value; + break; + case 54: + _coldResistence._permanent = value; + break; + case 55: + _poisonResistence._permanent = value; + break; + case 56: + _energyResistence._permanent = value; + break; + case 57: + _magicResistence._permanent = value; + break; + case 58: + _fireResistence._temporary = value; + break; + case 59: + _electricityResistence._temporary = value; + break; + case 60: + _coldResistence._temporary = value; + break; + case 61: + _poisonResistence._temporary = value; + break; + case 62: + _energyResistence._temporary = value; + break; + case 63: + _magicResistence._temporary = value; + break; + case 64: + _level._permanent = value; + break; + case 65: + // Set party food + party._food = value; + break; + case 69: + // Set levitate active + party._levitateActive = value != 0; + break; + case 70: + party._lightCount = value; + break; + case 71: + party._fireResistence = value; + break; + case 72: + party._electricityResistence = value; + break; + case 73: + party._coldResistence = value; + break; + case 74: + party._walkOnWaterActive = value != 0; + party._poisonResistence = value; + party._wizardEyeActive = value != 0; + party._coldResistence = value; + party._electricityResistence = value; + party._fireResistence = value; + party._lightCount = value; + party._levitateActive = value != 0; + break; + case 76: + // Set day of the year (0-99) + party._day = value; + break; + case 79: + party._wizardEyeActive = true; + break; + case 83: + scripts._nEdamageType = value; + break; + case 84: + party._mazeDirection = (Direction)value; + break; + case 85: + party._year = value; + break; + case 94: + party._walkOnWaterActive = value != 0; + break; + default: + break; + } +} + /*------------------------------------------------------------------------*/ void Roster::synchronize(Common::Serializer &s) { diff --git a/engines/xeen/party.h b/engines/xeen/party.h index dc87e88bd8..c77364bd10 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -165,6 +165,8 @@ public: int getCurrentLevel() const; int itemScan(int itemId) const; + + void setValue(int id, uint value); }; class Roster: public Common::Array<Character> { diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 5abd63a77e..57196af8b1 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -381,6 +381,10 @@ void Scripts::cmdSetChar(Common::Array<byte> ¶ms) { * Spawn a monster */ void Scripts::cmdSpawn(Common::Array<byte> ¶ms) { + Map &map = *_vm->_map; + if (params[0] >= map._mobData._monsters.size()) + map._mobData._monsters.resize(params[0] + 1); + MazeMonster &monster = _vm->_map->_mobData._monsters[params[0]]; MonsterStruct &monsterData = _vm->_map->_monsterData[monster._spriteId]; monster._position.x = params[1]; @@ -580,7 +584,43 @@ void Scripts::cmdReturn(Common::Array<byte> ¶ms) { cmdNoAction(params); } -void Scripts::cmdSetVar(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdSetVar(Common::Array<byte> ¶ms) { + Party &party = *_vm->_party; + bool flag = true; + uint val; + + switch (params[0]) { + case 25: + case 35: + case 101: + case 106: + val = (params[2] << 8) | params[1]; + break; + case 16: + case 34: + case 100: + val = (params[4] << 24) | (params[3] << 16) | (params[2] << 8) | params[3]; + break; + default: + val = params[1]; + break; + } + + if (_charIndex != 0 && _charIndex != 8) { + party._activeParty[_charIndex - 1].setValue(params[0], val); + } else { + // Set value for entire party + for (int idx = 0; idx < party._partyCount; ++idx) { + if (_charIndex == 0 || (_charIndex == 8 && _v2 != idx)) { + party._activeParty[idx].setValue(params[0], val); + } + } + } + + _var4F = true; + cmdNoAction(params); +} + void Scripts::cmdCutsceneEndClouds(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdWhoWill(Common::Array<byte> ¶ms) { diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 66dcb9b70b..6193153250 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -137,7 +137,6 @@ private: int _v2; int _var4F; - int _nEdamageType; MazeEvent *_event; Common::Point _currentPos; Common::Stack<StackEntry> _stack; @@ -214,6 +213,7 @@ public: int _animCounter; bool _eventSkipped; int _whoWill; + int _nEdamageType; public: Scripts(XeenEngine *vm); -- cgit v1.2.3 From b695934a1e5a62aa854bfc02bb4f10f562efe62b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 23:12:30 -0500 Subject: XEEN: Implemented cmdTeleport opcode --- engines/xeen/dialogs_string_input.cpp | 11 ++++- engines/xeen/items.h | 2 +- engines/xeen/screen.cpp | 4 +- engines/xeen/screen.h | 2 +- engines/xeen/scripts.cpp | 90 ++++++++++++++++++++++++++++++++--- engines/xeen/scripts.h | 14 ++++++ 6 files changed, 110 insertions(+), 13 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_string_input.cpp b/engines/xeen/dialogs_string_input.cpp index 03191f877d..ced4ad39ff 100644 --- a/engines/xeen/dialogs_string_input.cpp +++ b/engines/xeen/dialogs_string_input.cpp @@ -21,6 +21,7 @@ */ #include "xeen/dialogs_string_input.h" +#include "xeen/scripts.h" #include "xeen/xeen.h" namespace Xeen { @@ -38,6 +39,7 @@ int StringInput::execute(bool type, const Common::String &expected, const Common::String &title, int opcode) { Interface &intf = *_vm->_interface; Screen &screen = *_vm->_screen; + Scripts &scripts = *_vm->_scripts; Window &w = screen._windows[6]; SoundManager &sound = *_vm->_sound; int result = 0; @@ -58,8 +60,13 @@ int StringInput::execute(bool type, const Common::String &expected, // Load in the mirror list File f(Common::String::format("%smirr.txt", _vm->_files->_isDarkCc ? "dark" : "xeen")); - for (int idx = 0; f.pos() < f.size(); ++idx) { - if (line == f.readLine()) { + MirrorEntry me; + scripts._mirror.clear(); + while (me.synchronize(f)) + scripts._mirror.push_back(me); + + for (uint idx = 0; idx < scripts._mirror.size(); ++idx) { + if (line == scripts._mirror[idx]._name) { result = idx; sound.playFX(_vm->_files->_isDarkCc ? 35 : 61); break; diff --git a/engines/xeen/items.h b/engines/xeen/items.h index 9141deffa2..95a5519400 100644 --- a/engines/xeen/items.h +++ b/engines/xeen/items.h @@ -33,7 +33,7 @@ namespace Xeen { class XeenItem { public: int _material; - int _name; + uint _name; int _bonusFlags; bool _equipped; public: diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 16e4955cde..4eabc2b60a 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -180,9 +180,7 @@ void Window::drawList(DrawStruct *items, int count) { /** * Allows the user to enter a string */ -int Window::getString(Common::String &line, int maxLen, int maxWidth) { - Interface &intf = *_vm->_interface; - +int Window::getString(Common::String &line, uint maxLen, int maxWidth) { _vm->_noDirectionSense = true; Common::String msg = Common::String::format("\x03""l\t000\x04%03d\x03""c", maxWidth); writeString(msg); diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 5e4e46ca21..6e805c2aa3 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -95,7 +95,7 @@ public: void drawList(DrawStruct *items, int count); - int getString(Common::String &line, int maxLen, int maxWidth); + int getString(Common::String &line, uint maxLen, int maxWidth); }; class Screen: public FontSurface { diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 57196af8b1..39202c089d 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -69,6 +69,24 @@ void MazeEvents::synchronize(XeenSerializer &s) { /*------------------------------------------------------------------------*/ +bool MirrorEntry::synchronize(Common::SeekableReadStream &s) { + if (s.pos() >= s.size()) + return false; + + char buffer[28]; + s.read(buffer, 28); + buffer[27] = '\0'; + + _name = Common::String(buffer); + _mapId = s.readByte(); + _position.x = s.readSByte(); + _position.y = s.readSByte(); + _direction = s.readSByte(); + return true; +} + +/*------------------------------------------------------------------------*/ + Scripts::Scripts(XeenEngine *vm) : _vm(vm) { Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0); _whoWill = 0; @@ -82,6 +100,7 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) { _nEdamageType = 0; _animCounter = 0; _eventSkipped = false; + _mirrorId = -1; } void Scripts::checkEvents() { @@ -271,7 +290,67 @@ void Scripts::cmdPlayFX(Common::Array<byte> ¶ms) { } void Scripts::cmdTeleport(Common::Array<byte> ¶ms) { - error("TODO"); + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + + screen.closeWindows(); + _var4F = true; + + int mapId; + Common::Point pt; + + if (params[0]) { + mapId = params[0]; + pt = Common::Point((int8)params[1], (int8)params[2]); + } else { + assert(_mirrorId > 0); + MirrorEntry &me = _mirror[_mirrorId - 1]; + mapId = me._mapId; + pt = me._position; + if (me._direction != -1) + party._mazeDirection = (Direction)me._direction; + + if (pt.x == 0 && pt.y == 0) + pt.x = 999; + + sound.playFX(51); + } + + party._stepped = true; + if (mapId != party._mazeId) { + switch (map._mobData._objects[intf._objNumber - 1]._spriteId) { + case 47: + sound.playFX(45); + break; + case 48: + sound.playFX(44); + break; + default: + break; + } + + // Load the new map + map.load(mapId); + } + + if (pt.x == 999) { + party._mazePosition = map.mazeData()._runPosition; + } else { + party._mazePosition = pt; + } + + events.clearEvents(); + + if (_event->_opcode == OP_TeleportAndContinue) { + intf.draw3d(true); + _lineNum = 0; + } else { + cmdExit(params); + } } /** @@ -586,7 +665,6 @@ void Scripts::cmdReturn(Common::Array<byte> ¶ms) { void Scripts::cmdSetVar(Common::Array<byte> ¶ms) { Party &party = *_vm->_party; - bool flag = true; uint val; switch (params[0]) { @@ -898,22 +976,22 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { if (mask < 82) { for (int idx = 0; idx < 9; ++idx) { if (mask == 35) { - if ((int)ps._weapons[idx]._name == mask) { + if (ps._weapons[idx]._name == mask) { v = mask; break; } } else if (mask < 49) { - if ((int)ps._armor[idx]._name == (mask - 35)) { + if (ps._armor[idx]._name == (mask - 35)) { v = mask; break; } } else if (mask < 60) { - if ((int)ps._accessories[idx]._name == (mask - 49)) { + if (ps._accessories[idx]._name == (mask - 49)) { v = mask; break; } } else { - if ((int)ps._misc[idx]._name == (mask - 60)) { + if (ps._misc[idx]._name == (mask - 60)) { v = mask; break; } diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 6193153250..c0168e208f 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -29,6 +29,7 @@ #include "common/stack.h" #include "common/str-array.h" #include "xeen/files.h" +#include "xeen/party.h" namespace Xeen { @@ -124,6 +125,17 @@ struct StackEntry : public Common::Point { StackEntry(const Common::Point &pt, int l) : Common::Point(pt), line(l) {} }; +struct MirrorEntry { + Common::String _name; + int _mapId; + Common::Point _position; + int _direction; + + MirrorEntry() : _mapId(0), _direction(DIR_ALL) {} + + bool synchronize(Common::SeekableReadStream &s); +}; + class Scripts { private: XeenEngine *_vm; @@ -134,6 +146,7 @@ private: int _treasureGems; int _lineNum; int _charIndex; + int _mirrorId; int _v2; int _var4F; @@ -214,6 +227,7 @@ public: bool _eventSkipped; int _whoWill; int _nEdamageType; + Common::Array<MirrorEntry> _mirror; public: Scripts(XeenEngine *vm); -- cgit v1.2.3 From 51dba2606e1cf202d73d7c77ba15939268bb6efd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 23:49:12 -0500 Subject: XEEN: Simplify _currentWall back to int for now --- engines/xeen/interface.cpp | 2 +- engines/xeen/interface_map.cpp | 16 ++++++++-------- engines/xeen/map.cpp | 28 ++++++++++++++-------------- engines/xeen/map.h | 2 +- engines/xeen/scripts.cpp | 5 ++++- 5 files changed, 28 insertions(+), 25 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 44e2326c1f..f85e19d99f 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -809,7 +809,7 @@ bool Interface::checkMoveDirection(int key) { if (map._isOutdoors) { party._mazeDirection = dir; - switch ((int)map._currentWall._outdoors._surfaceId) { + switch (map._currentWall) { case 5: if (_vm->_files->_isDarkCc) goto check; diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 04f7355603..43a467df9b 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -1176,7 +1176,7 @@ void InterfaceMap::setMazeBits() { break; } - _thinWall = (_vm->_map->_currentWall._data != INVALID_CELL) && _wo[27]; + _thinWall = (_vm->_map->_currentWall != INVALID_CELL) && _wo[27]; switch (_vm->_map->getCell(8) - 1) { case 1: @@ -4423,25 +4423,25 @@ void InterfaceMap::drawOutdoors() { for (int idx = 0; idx < 9; ++idx) { map.getCell(TERRAIN_INDEXES1[idx]); - _outdoorList[36 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data]; + _outdoorList[36 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall]; } for (int idx = 0; idx < 5; ++idx) { map.getCell(TERRAIN_INDEXES2[idx]); - _outdoorList[61 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data]; + _outdoorList[61 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall]; } for (int idx = 0; idx < 3; ++idx) { map.getCell(TERRAIN_INDEXES3[idx]); - _outdoorList[84 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data]; + _outdoorList[84 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall]; } for (int idx = 0; idx < 5; ++idx) { map.getCell(TERRAIN_INDEXES4[idx]); - _outdoorList[103 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data]; + _outdoorList[103 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall]; } map.getCell(1); - _outdoorList[108]._sprites = &map._wallSprites._surfaces[map._currentWall._data]; - _outdoorList[109]._sprites = &map._wallSprites._surfaces[map._currentWall._data]; - _outdoorList[110]._sprites = &map._wallSprites._surfaces[map._currentWall._data]; + _outdoorList[108]._sprites = &map._wallSprites._surfaces[map._currentWall]; + _outdoorList[109]._sprites = &map._wallSprites._surfaces[map._currentWall]; + _outdoorList[110]._sprites = &map._wallSprites._surfaces[map._currentWall]; _outdoorList._sky1._flags = _outdoorList._sky2._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0; _outdoorList._groundSprite._flags = _flipWater ? SPRFLAG_HORIZ_FLIPPED : 0; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index ae38b77ed6..52dc4273aa 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -866,7 +866,7 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { _mazeDataIndex = 0; _currentSteppedOn = false; _currentSurfaceId = 0; - _currentWall._data = 0; + _currentWall = 0; _currentTile = 0; _currentIsGrate = false; _currentCantRest = false; @@ -1398,7 +1398,7 @@ int Map::getCell(int idx) { } else { _currentSurfaceId = (mapId >= 25 && mapId <= 27) ? 7 : 0; } - _currentWall._data = INVALID_CELL; + _currentWall = INVALID_CELL; return INVALID_CELL; } @@ -1418,7 +1418,7 @@ int Map::getCell(int idx) { if (!mapId) { if (_isOutdoors) { _currentSurfaceId = SURFTYPE_SPACE; - _currentWall._data = 0; + _currentWall = 0; return 0; } else { if (_vm->_files->_isDarkCc) { @@ -1432,7 +1432,7 @@ int Map::getCell(int idx) { _currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT; } - _currentWall._data = INVALID_CELL; + _currentWall = INVALID_CELL; return INVALID_CELL; } @@ -1454,7 +1454,7 @@ int Map::getCell(int idx) { if (!mapId) { if (_isOutdoors) { _currentSurfaceId = SURFTYPE_SPACE; - _currentWall._data = 0; + _currentWall = 0; return 0; } else { if (_vm->_files->_isDarkCc) { @@ -1468,7 +1468,7 @@ int Map::getCell(int idx) { _currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT; } - _currentWall._data = INVALID_CELL; + _currentWall = INVALID_CELL; return INVALID_CELL; } } @@ -1478,16 +1478,16 @@ int Map::getCell(int idx) { ++_mazeDataIndex; } - MazeWallLayers &wallLayers = _mazeData[_mazeDataIndex]._wallData[pt.y][pt.x]; + int wallData = _mazeData[_mazeDataIndex]._wallData[pt.y][pt.x]._data; if (_isOutdoors) { if (mapId) { // TODO: tile is set to word of (wallLayers >> 8) && 0xff? Makes no sense - _currentTile = wallLayers._outdoors._surfaceId; - _currentWall = wallLayers; - _currentSurfaceId = wallLayers._outdoors._surfaceId; + _currentTile = (wallData >> 8) & 0xFF; + _currentWall = (wallData >> 4) & 0xF; + _currentSurfaceId = wallData & 0xF; } else { _currentSurfaceId = SURFTYPE_DEFAULT; - _currentWall._data = 0; + _currentWall = 0; _currentTile = 0; } } else { @@ -1499,11 +1499,11 @@ int Map::getCell(int idx) { else _currentSurfaceId = _mazeData[_mazeDataIndex]._cells[pt.y][pt.x]._surfaceId; - _currentWall = wallLayers; - return (_currentWall._data >> WALL_SHIFTS[dir][idx]) & 0xF; + _currentWall = wallData; + return (_currentWall >> WALL_SHIFTS[dir][idx]) & 0xF; } - return _currentWall._data; + return _currentWall; } void Map::loadSky() { diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 499b451bbc..f878a0d0d5 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -370,7 +370,7 @@ public: bool _currentIsEvent; int _currentSky; int _currentMonsterFlags; - MazeWallLayers _currentWall; + int _currentWall; int _currentTile; int _currentSurfaceId; bool _currentSteppedOn; diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 39202c089d..ad24985b31 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -322,7 +322,10 @@ void Scripts::cmdTeleport(Common::Array<byte> ¶ms) { party._stepped = true; if (mapId != party._mazeId) { - switch (map._mobData._objects[intf._objNumber - 1]._spriteId) { + int spriteId = (intf._objNumber == 0) ? -1 : + map._mobData._objects[intf._objNumber - 1]._spriteId; + + switch (spriteId) { case 47: sound.playFX(45); break; -- cgit v1.2.3 From 482c2b2ac8cff51d435d20b348e668dd77386af2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 23:53:56 -0500 Subject: XEEN: Fix immediate crash in outdoors rendering --- engines/xeen/interface_map.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 43a467df9b..23b709d391 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -4423,25 +4423,30 @@ void InterfaceMap::drawOutdoors() { for (int idx = 0; idx < 9; ++idx) { map.getCell(TERRAIN_INDEXES1[idx]); - _outdoorList[36 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall]; + SpriteResource &spr = map._wallSprites._surfaces[map._currentWall]; + _outdoorList[36 + idx]._sprites = spr.size() == 0 ? (SpriteResource *)nullptr : &spr; } for (int idx = 0; idx < 5; ++idx) { map.getCell(TERRAIN_INDEXES2[idx]); - _outdoorList[61 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall]; + SpriteResource &spr = map._wallSprites._surfaces[map._currentWall]; + _outdoorList[61 + idx]._sprites = spr.size() == 0 ? (SpriteResource *)nullptr : &spr; } for (int idx = 0; idx < 3; ++idx) { map.getCell(TERRAIN_INDEXES3[idx]); - _outdoorList[84 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall]; + SpriteResource &spr = map._wallSprites._surfaces[map._currentWall]; + _outdoorList[84 + idx]._sprites = spr.size() == 0 ? (SpriteResource *)nullptr : &spr; } for (int idx = 0; idx < 5; ++idx) { map.getCell(TERRAIN_INDEXES4[idx]); - _outdoorList[103 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall]; + SpriteResource &spr = map._wallSprites._surfaces[map._currentWall]; + _outdoorList[103 + idx]._sprites = spr.size() == 0 ? (SpriteResource *)nullptr : &spr; } map.getCell(1); - _outdoorList[108]._sprites = &map._wallSprites._surfaces[map._currentWall]; - _outdoorList[109]._sprites = &map._wallSprites._surfaces[map._currentWall]; - _outdoorList[110]._sprites = &map._wallSprites._surfaces[map._currentWall]; + SpriteResource &surface = map._wallSprites._surfaces[map._currentWall]; + _outdoorList[108]._sprites = surface.size() == 0 ? (SpriteResource *)nullptr : &surface; + _outdoorList[109]._sprites = _outdoorList[108]._sprites; + _outdoorList[110]._sprites = _outdoorList[108]._sprites; _outdoorList._sky1._flags = _outdoorList._sky2._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0; _outdoorList._groundSprite._flags = _flipWater ? SPRFLAG_HORIZ_FLIPPED : 0; -- cgit v1.2.3 From 3135d1e0a756e2d7927d3ffa1608351252654bd4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 25 Jan 2015 08:24:18 -0500 Subject: XEEN: Fix rendering in drawOutdoors --- engines/xeen/interface_map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 23b709d391..c0f574686c 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -4399,7 +4399,7 @@ void InterfaceMap::drawOutdoors() { for (int cellIndex = 0; cellIndex < 25; ++cellIndex) { map.getCell(cellIndex == 24 ? 2 : DRAW_NUMBERS[cellIndex]); - DrawStruct &drawStruct = _indoorList._groundTiles[cellIndex]; + DrawStruct &drawStruct = _outdoorList._groundTiles[cellIndex]; SpriteResource &sprites = map._surfaceSprites[map._currentSurfaceId]; drawStruct._sprites = sprites.empty() ? (SpriteResource *)nullptr : &sprites; -- cgit v1.2.3 From 7b387dbd89c303c73dd2763a5c05ff0d9d64e4b4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 25 Jan 2015 09:01:21 -0500 Subject: XEEN: Fix clearing Please Wait window after changing maps --- engines/xeen/scripts.cpp | 13 +++++++++++-- engines/xeen/scripts.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index ad24985b31..6355c1cd2f 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -101,15 +101,17 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) { _animCounter = 0; _eventSkipped = false; _mirrorId = -1; + _refreshIcons = false; } void Scripts::checkEvents() { Combat &combat = *_vm->_combat; -// Interface &intf = *_vm->_interface; + Interface &intf = *_vm->_interface; Map &map = *_vm->_map; Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; -// int var18 = 0; + _refreshIcons = false; _itemType = 0; _var4F = 0; bool var50 = false; @@ -163,6 +165,12 @@ void Scripts::checkEvents() { } } while (!_vm->shouldQuit() && _lineNum != -1); + intf._face1State = intf._face2State = 2; + if (_refreshIcons) { + screen.closeWindows(); + intf.charIconsPrint(true); + } + // TODO } @@ -669,6 +677,7 @@ void Scripts::cmdReturn(Common::Array<byte> ¶ms) { void Scripts::cmdSetVar(Common::Array<byte> ¶ms) { Party &party = *_vm->_party; uint val; + _refreshIcons = true; switch (params[0]) { case 25: diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index c0168e208f..72ddfbc6ec 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -147,6 +147,7 @@ private: int _lineNum; int _charIndex; int _mirrorId; + int _refreshIcons; int _v2; int _var4F; -- cgit v1.2.3 From ef283252b36b361e3775d07e8f9fe887af1ab9ba Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 25 Jan 2015 11:18:00 -0500 Subject: XEEN: Fix keyboard keys in YesNo dialog --- engines/xeen/dialogs_yesno.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp index 6f74d86ca4..940f5b6e08 100644 --- a/engines/xeen/dialogs_yesno.cpp +++ b/engines/xeen/dialogs_yesno.cpp @@ -53,8 +53,8 @@ bool YesNo::execute(bool type, int v2) { confirmSprites.draw(screen, 2, Common::Point(260, 75)); screen._windows[34].update(); - addButton(Common::Rect(235, 75, 259, 95), 'Y', &confirmSprites); - addButton(Common::Rect(260, 75, 284, 95), 'N', &confirmSprites); + addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_y, &confirmSprites); + addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_n, &confirmSprites); intf._face1State = map._headData[party._mazePosition.y][party._mazePosition.x]._left; intf._face2State = map._headData[party._mazePosition.y][party._mazePosition.x]._right; @@ -76,10 +76,10 @@ bool YesNo::execute(bool type, int v2) { if (!_buttonValue) continue; - if (type || _buttonValue == 'Y') { + if (type || _buttonValue == Common::KEYCODE_y) { result = true; break; - } else if (_buttonValue == 'N' || _buttonValue == Common::KEYCODE_ESCAPE) + } else if (_buttonValue == Common::KEYCODE_n || _buttonValue == Common::KEYCODE_ESCAPE) break; } -- cgit v1.2.3 From 50d3d79d7ff415be7210cc251d29716634a6292d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 25 Jan 2015 12:06:23 -0500 Subject: XEEN: Revert window restriction, since all window draws use absolute x,y --- engines/xeen/screen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 4eabc2b60a..5088829cf6 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -38,7 +38,7 @@ Window::Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border, _vm(vm), _enabled(false), _a(a), _border(border), _xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) { setBounds(bounds); - create(_vm->_screen, bounds); + create(_vm->_screen, Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); } void Window::setBounds(const Common::Rect &r) { -- cgit v1.2.3 From 94ce2c1e6f46a858725dfab2c587f5069acdef8b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 25 Jan 2015 19:32:57 -0500 Subject: XEEN: Fix display of outdoors objects --- engines/xeen/interface_map.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index c0f574686c..107f9ecf5a 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -3384,6 +3384,7 @@ void InterfaceMap::setOutdoorsObjects() { DrawStruct &ds = _outdoorList[111]; ds._x = OUTDOOR_OBJECT_X[posIndex][0]; ds._y = MAP_OBJECT_Y[posIndex][0]; + ds._frame = obj._frame; ds._sprites = obj._sprites; ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -3398,6 +3399,7 @@ void InterfaceMap::setOutdoorsObjects() { DrawStruct &ds = _outdoorList[87]; ds._x = OUTDOOR_OBJECT_X[posIndex][1]; ds._y = MAP_OBJECT_Y[posIndex][1]; + ds._frame = obj._frame; ds._sprites = obj._sprites; ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -3411,6 +3413,7 @@ void InterfaceMap::setOutdoorsObjects() { DrawStruct &ds = _outdoorList[88]; ds._x = OUTDOOR_OBJECT_X[posIndex][2]; ds._y = MAP_OBJECT_Y[posIndex][2]; + ds._frame = obj._frame; ds._sprites = obj._sprites; ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -3424,6 +3427,7 @@ void InterfaceMap::setOutdoorsObjects() { DrawStruct &ds = _outdoorList[89]; ds._x = OUTDOOR_OBJECT_X[posIndex][3]; ds._y = MAP_OBJECT_Y[posIndex][3]; + ds._frame = obj._frame; ds._sprites = obj._sprites; ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -3437,6 +3441,7 @@ void InterfaceMap::setOutdoorsObjects() { DrawStruct &ds = _outdoorList[66]; ds._x = OUTDOOR_OBJECT_X[posIndex][4]; ds._y = MAP_OBJECT_Y[posIndex][4]; + ds._frame = obj._frame; ds._sprites = obj._sprites; ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -3450,6 +3455,7 @@ void InterfaceMap::setOutdoorsObjects() { DrawStruct &ds = _outdoorList[67]; ds._x = OUTDOOR_OBJECT_X[posIndex][5]; ds._y = MAP_OBJECT_Y[posIndex][5]; + ds._frame = obj._frame; ds._sprites = obj._sprites; ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -3463,6 +3469,7 @@ void InterfaceMap::setOutdoorsObjects() { DrawStruct &ds = _outdoorList[68]; ds._x = OUTDOOR_OBJECT_X[posIndex][6]; ds._y = MAP_OBJECT_Y[posIndex][6]; + ds._frame = obj._frame; ds._sprites = obj._sprites; ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -3476,6 +3483,7 @@ void InterfaceMap::setOutdoorsObjects() { DrawStruct &ds = _outdoorList[37]; ds._x = OUTDOOR_OBJECT_X[posIndex][7]; ds._y = MAP_OBJECT_Y[posIndex][7]; + ds._frame = obj._frame; ds._sprites = obj._sprites; ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -3489,6 +3497,7 @@ void InterfaceMap::setOutdoorsObjects() { DrawStruct &ds = _outdoorList[38]; ds._x = OUTDOOR_OBJECT_X[posIndex][8]; ds._y = MAP_OBJECT_Y[posIndex][8]; + ds._frame = obj._frame; ds._sprites = obj._sprites; ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -3502,6 +3511,7 @@ void InterfaceMap::setOutdoorsObjects() { DrawStruct &ds = _outdoorList[40]; ds._x = OUTDOOR_OBJECT_X[posIndex][10]; ds._y = MAP_OBJECT_Y[posIndex][10]; + ds._frame = obj._frame; ds._sprites = obj._sprites; ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -3515,6 +3525,7 @@ void InterfaceMap::setOutdoorsObjects() { DrawStruct &ds = _outdoorList[39]; ds._x = OUTDOOR_OBJECT_X[posIndex][9]; ds._y = MAP_OBJECT_Y[posIndex][9]; + ds._frame = obj._frame; ds._sprites = obj._sprites; ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -3528,6 +3539,7 @@ void InterfaceMap::setOutdoorsObjects() { DrawStruct &ds = _outdoorList[41]; ds._x = OUTDOOR_OBJECT_X[posIndex][11]; ds._y = MAP_OBJECT_Y[posIndex][11]; + ds._frame = obj._frame; ds._sprites = obj._sprites; ds._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -4421,10 +4433,11 @@ void InterfaceMap::drawOutdoors() { const int TERRAIN_INDEXES3[3] = { 11, 16, 13 }; const int TERRAIN_INDEXES4[5] = { 5, 9, 7, 0, 4 }; + // Loops to set draw entries for the terrain for (int idx = 0; idx < 9; ++idx) { map.getCell(TERRAIN_INDEXES1[idx]); SpriteResource &spr = map._wallSprites._surfaces[map._currentWall]; - _outdoorList[36 + idx]._sprites = spr.size() == 0 ? (SpriteResource *)nullptr : &spr; + _outdoorList[28 + idx]._sprites = spr.size() == 0 ? (SpriteResource *)nullptr : &spr; } for (int idx = 0; idx < 5; ++idx) { map.getCell(TERRAIN_INDEXES2[idx]); -- cgit v1.2.3 From 84741d73a09f45232b0dccd26df5b05eb6c80476 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 25 Jan 2015 20:05:35 -0500 Subject: XEEN: Properly clear previous MazeData when loading a new map --- engines/xeen/map.cpp | 13 ++++++++++++- engines/xeen/map.h | 4 ++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 52dc4273aa..51e87ef97e 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -491,6 +491,10 @@ void MonsterData::synchronize(Common::SeekableReadStream &s) { /*------------------------------------------------------------------------*/ SurroundingMazes::SurroundingMazes() { + clear(); +} + +void SurroundingMazes::clear() { _north = 0; _east = 0; _south = 0; @@ -541,6 +545,10 @@ void MazeDifficulties::synchronize(Common::SeekableReadStream &s) { /*------------------------------------------------------------------------*/ MazeData::MazeData() { + clear(); +} + +void MazeData::clear() { for (int y = 0; y < MAP_HEIGHT; ++y) { for (int x = 0; x < MAP_WIDTH; ++x) _wallData[y][x]._data = 0; @@ -550,6 +558,7 @@ MazeData::MazeData() { _surfaceTypes[y] = 0; } _mazeNumber = 0; + _surroundingMazes.clear(); _mazeFlags = _mazeFlags2 = 0; _floorType = 0; _trapDamage = 0; @@ -963,7 +972,9 @@ void Map::load(int mapId) { for (int idx = 0; idx < 9; ++idx, ++mazeDataP) { mazeDataP->_mazeId = mapId; - if (mapId != 0) { + if (mapId == 0) { + mazeDataP->clear(); + } else { // Load in the maze's data file Common::String datName = Common::String::format("maze%c%03d.dat", (mapId >= 100) ? 'x' : '0', mapId); diff --git a/engines/xeen/map.h b/engines/xeen/map.h index f878a0d0d5..7d268efb8e 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -112,6 +112,8 @@ public: public: SurroundingMazes(); + void clear(); + void synchronize(Common::SeekableReadStream &s); int &operator[](int idx); @@ -199,6 +201,8 @@ public: public: MazeData(); + void clear(); + void synchronize(Common::SeekableReadStream &s); void setAllTilesStepped(); -- cgit v1.2.3 From 2abce62b8fd1b29d2c351ca7502f21010882674f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 25 Jan 2015 21:19:59 -0500 Subject: XEEN: Add skeleton for spells class --- engines/xeen/module.mk | 1 + engines/xeen/resources.cpp | 2 ++ engines/xeen/resources.h | 2 ++ engines/xeen/scripts.cpp | 88 ++++++++++++++++++++++++++++++---------------- engines/xeen/scripts.h | 11 +++--- engines/xeen/spells.cpp | 40 +++++++++++++++++++++ engines/xeen/spells.h | 46 ++++++++++++++++++++++++ engines/xeen/xeen.cpp | 3 ++ engines/xeen/xeen.h | 2 ++ 9 files changed, 160 insertions(+), 35 deletions(-) create mode 100644 engines/xeen/spells.cpp create mode 100644 engines/xeen/spells.h (limited to 'engines/xeen') diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index ea6ea8c073..c5348442ec 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -26,6 +26,7 @@ MODULE_OBJS := \ screen.o \ scripts.o \ sound.o \ + spells.o \ sprites.o \ xeen.o \ xsurface.o diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 26c33cad11..0f48073044 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -75,6 +75,8 @@ const char *const WHATS_THE_PASSWORD = "What's the Password?"; const char *const IN_NO_CONDITION = "\x0B""007%s is not in any condition to perform actions!"; +const char *const NOTHING_HERE = "\x03""c\x0B""010Nothing here."; + const char *const TERRAIN_TYPES[6] = { "town", "cave", "towr", "cstl", "dung", "scfi" }; diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 2e77e95dbb..8537835630 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -40,6 +40,8 @@ extern const char *const WHATS_THE_PASSWORD; extern const char *const IN_NO_CONDITION; +extern const char *const NOTHING_HERE; + extern const char *const TERRAIN_TYPES[6]; extern const char *const SURFACE_TYPE_NAMES[15]; diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 6355c1cd2f..665fd0d632 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -96,25 +96,30 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) { _treasureGems = 0; _lineNum = 0; _charIndex = 0; - _v2 = 0; + _v2 = false; _nEdamageType = 0; _animCounter = 0; _eventSkipped = false; _mirrorId = -1; _refreshIcons = false; + _scriptResult = false; + _scriptExecuted = false; + _var50 = false; } -void Scripts::checkEvents() { +bool Scripts::checkEvents() { Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; Map &map = *_vm->_map; Party &party = *_vm->_party; Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; _refreshIcons = false; _itemType = 0; - _var4F = 0; - bool var50 = false; + _scriptExecuted = false; + _var50 = false; _whoWill = 0; Mode oldMode = _vm->_mode; Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0); @@ -128,12 +133,12 @@ void Scripts::checkEvents() { do { _lineNum = 0; -// int varA = 0; + _scriptResult = false; _animCounter = 0; // int var4E = 0; _currentPos = party._mazePosition; _charIndex = 1; - _v2 = 1; + _v2 = true; _nEdamageType = 0; // int var40 = -1; @@ -156,7 +161,7 @@ void Scripts::checkEvents() { doOpcode(event); break; } else { - var50 = true; + _var50 = true; } } } @@ -172,6 +177,35 @@ void Scripts::checkEvents() { } // TODO + + _animCounter = 0; + _vm->_mode = oldMode; + screen.closeWindows(); + + if (_scriptExecuted || !intf._objNumber || _var50) { + if (_var50 && !_scriptExecuted && intf._objNumber && !map._currentIsEvent) { + sound.playFX(21); + } + } else { + Window &w = screen._windows[38]; + w.open(); + w.writeString(NOTHING_HERE); + w.update(); + + do { + intf.draw3d(true); + events.updateGameCounter(); + events.wait(1, true); + } while (!events.isKeyMousePressed()); + events.clearEvents(); + + w.close(); + } + + _v2 = true; + Common::fill(&_charFX[0], &_charFX[6], 0); + + return _scriptResult; } void Scripts::giveTreasure() { @@ -231,7 +265,6 @@ void Scripts::cmdDisplay1(Common::Array<byte> ¶ms) { screen._windows[38].writeString(msg); screen._windows[38].update(); - _var4F = true; cmdNoAction(params); } @@ -247,7 +280,6 @@ void Scripts::cmdDoorTextSml(Common::Array<byte> ¶ms) { intf._upDoorText = true; intf.draw3d(true); - _var4F = true; cmdNoAction(params); } @@ -263,7 +295,6 @@ void Scripts::cmdDoorTextLrg(Common::Array<byte> ¶ms) { intf._upDoorText = true; intf.draw3d(true); - _var4F = true; cmdNoAction(params); } @@ -279,7 +310,6 @@ void Scripts::cmdSignText(Common::Array<byte> ¶ms) { intf._upDoorText = true; intf.draw3d(true); - _var4F = true; cmdNoAction(params); } @@ -293,7 +323,6 @@ void Scripts::cmdNPC(Common::Array<byte> ¶ms) { void Scripts::cmdPlayFX(Common::Array<byte> ¶ms) { _vm->_sound->playFX(params[0]); - _var4F = true; cmdNoAction(params); } @@ -306,7 +335,6 @@ void Scripts::cmdTeleport(Common::Array<byte> ¶ms) { SoundManager &sound = *_vm->_sound; screen.closeWindows(); - _var4F = true; int mapId; Common::Point pt; @@ -407,7 +435,6 @@ void Scripts::cmdIf(Common::Array<byte> ¶ms) { if (result) _lineNum = newLineNum - 1; - _var4F = true; cmdNoAction(params); } @@ -463,7 +490,7 @@ void Scripts::cmdSetChar(Common::Array<byte> ¶ms) { _charIndex = _vm->getRandomNumber(1, _vm->_party->_partyCount); } - _v2 = 1; + _v2 = true; cmdNoAction(params); } @@ -484,11 +511,15 @@ void Scripts::cmdSpawn(Common::Array<byte> ¶ms) { monster._isAttacking = params[1] != 0; monster._hp = monsterData._hp; - _var4F = 1; cmdNoAction(params); } -void Scripts::cmdDoTownEvent(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdDoTownEvent(Common::Array<byte> ¶ms) { + _scriptResult = doTownEvent(params[0]); + _vm->_party->_stepped = true; + + cmdExit(params); +} /** * Stop executing the script @@ -510,7 +541,6 @@ void Scripts::cmdAlterMap(Common::Array<byte> ¶ms) { map.setWall(Common::Point(params[0], params[1]), (Direction)params[2], params[3]); } - _var4F = true; cmdNoAction(params); } @@ -554,7 +584,6 @@ void Scripts::cmdGiveExtended(Common::Array<byte> ¶ms) { if (result) _lineNum = newLineNum - 1; - _var4F = true; cmdNoAction(params); } @@ -610,7 +639,6 @@ void Scripts::cmdConfirmWord(Common::Array<byte> ¶ms) { } } - _var4F = true; cmdNoAction(params); } @@ -624,7 +652,6 @@ void Scripts::cmdJumpRnd(Common::Array<byte> ¶ms) { if (v == params[1]) _lineNum = params[2] - 1; - _var4F = true; cmdNoAction(params); } @@ -644,7 +671,6 @@ void Scripts::cmdAlterEvent(Common::Array<byte> ¶ms) { } } - _var4F = true; cmdNoAction(params); } @@ -657,7 +683,6 @@ void Scripts::cmdCallEvent(Common::Array<byte> ¶ms) { _currentPos = Common::Point(params[0], params[1]); _lineNum = params[2] - 1; - _var4F = true; cmdNoAction(params); } @@ -670,7 +695,6 @@ void Scripts::cmdReturn(Common::Array<byte> ¶ms) { _currentPos = se; _lineNum = se.line; - _var4F = true; cmdNoAction(params); } @@ -707,7 +731,6 @@ void Scripts::cmdSetVar(Common::Array<byte> ¶ms) { } } - _var4F = true; cmdNoAction(params); } @@ -716,7 +739,6 @@ void Scripts::cmdCutsceneEndClouds(Common::Array<byte> ¶ms) { error("TODO"); void Scripts::cmdWhoWill(Common::Array<byte> ¶ms) { _charIndex = WhoWill::show(_vm, params[0], params[1], true); - _var4F = true; if (_charIndex == 0) cmdExit(params); else @@ -751,7 +773,6 @@ void Scripts::cmdMakeNothingHere(Common::Array<byte> ¶ms) { evt._opcode = OP_None; } - _var4F = true; cmdExit(params); } @@ -777,7 +798,6 @@ void Scripts::cmdExchObj(Common::Array<byte> ¶ms) { obj1._position = obj2._position; obj2._position = pt; - _var4F = true; cmdNoAction(params); } @@ -787,7 +807,6 @@ void Scripts::cmdFallToMap(Common::Array<byte> ¶ms) { party._fallPosition = Common::Point(params[1], params[2]); party._fallDamage = params[3]; - _var4F = true; _lineNum = -1; } @@ -806,7 +825,6 @@ void Scripts::cmdGoto(Common::Array<byte> ¶ms) { if (params[0] == map._currentSurfaceId) _lineNum = params[1] - 1; - _var4F = true; cmdNoAction(params); } @@ -815,7 +833,6 @@ void Scripts::cmdGoto(Common::Array<byte> ¶ms) { */ void Scripts::cmdGotoRandom(Common::Array<byte> ¶ms) { _lineNum = params[_vm->getRandomNumber(1, params[0])] - 1; - _var4F = true; cmdNoAction(params); } @@ -1254,6 +1271,15 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { } } +bool Scripts::doTownEvent(int actionId) { + if (actionId == 12) + return false; + + + + return false; +} + bool Scripts::copyProtectionCheck() { // Currentl not implemented return true; diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 72ddfbc6ec..44290eef47 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -148,9 +148,10 @@ private: int _charIndex; int _mirrorId; int _refreshIcons; - - int _v2; - int _var4F; + int _scriptResult; + bool _v2; + bool _scriptExecuted; + bool _var50; MazeEvent *_event; Common::Point _currentPos; Common::Stack<StackEntry> _stack; @@ -222,6 +223,8 @@ private: bool ifProc(int action, uint32 mask, int mode, int charIndex); + bool doTownEvent(int actionId); + bool copyProtectionCheck(); public: int _animCounter; @@ -232,7 +235,7 @@ public: public: Scripts(XeenEngine *vm); - void checkEvents(); + bool checkEvents(); void giveTreasure(); diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp new file mode 100644 index 0000000000..8a5126c381 --- /dev/null +++ b/engines/xeen/spells.cpp @@ -0,0 +1,40 @@ +/* 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 "xeen/spells.h" +#include "xeen/files.h" +#include "xeen/xeen.h" + +namespace Xeen { + +Spells::Spells(XeenEngine *vm) : _vm(vm) { + load(); +} + +void Spells::load() { + File f("spells.xen"); + while (f.pos() < f.size()) + _spellNames.push_back(f.readString()); + f.close(); +} + +} // End of namespace Xeen diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h new file mode 100644 index 0000000000..adb957c26a --- /dev/null +++ b/engines/xeen/spells.h @@ -0,0 +1,46 @@ +/* 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 XEEN_SPELLS_H +#define XEEN_SPELLS_H + +#include "common/scummsys.h" +#include "common/str-array.h" + +namespace Xeen { + +class XeenEngine; + +class Spells { +private: + XeenEngine *_vm; + + void load(); +public: + Common::StringArray _spellNames; +public: + Spells(XeenEngine *vm); +}; + +} // End of namespace Xeen + +#endif /* XEEN_SPELLS_H */ diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 8489f86ed5..8879b15a0d 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -47,6 +47,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _screen = nullptr; _scripts = nullptr; _sound = nullptr; + _spells = nullptr; _eventData = nullptr; _dangerSenseAllowed = false; _noDirectionSense = false; @@ -67,6 +68,7 @@ XeenEngine::~XeenEngine() { delete _screen; delete _scripts; delete _sound; + delete _spells; delete _eventData; delete _files; } @@ -91,6 +93,7 @@ void XeenEngine::initialize() { _scripts = new Scripts(this); _screen->setupWindows(); _sound = new SoundManager(this); + _spells = new Spells(this); File f("029.obj"); _eventData = f.readStream(f.size()); diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index b60908ddfe..38c7beb057 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -43,6 +43,7 @@ #include "xeen/screen.h" #include "xeen/scripts.h" #include "xeen/sound.h" +#include "xeen/spells.h" /** * This is the namespace of the Xeen engine. @@ -140,6 +141,7 @@ public: Screen *_screen; Scripts *_scripts; SoundManager *_sound; + Spells *_spells; Treasure _treasure; Mode _mode; GameEvent _gameEvent; -- cgit v1.2.3 From f11e11006b5cbe7d9bcd547f98ab2b4dba358764 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 25 Jan 2015 23:59:16 -0500 Subject: XEEN: Beginnings of Town class, implemented handleAction --- engines/xeen/interface.cpp | 8 + engines/xeen/interface.h | 4 + engines/xeen/interface_map.cpp | 2 +- engines/xeen/interface_map.h | 20 ++- engines/xeen/module.mk | 1 + engines/xeen/resources.cpp | 21 ++- engines/xeen/resources.h | 8 + engines/xeen/scripts.cpp | 21 +-- engines/xeen/scripts.h | 4 +- engines/xeen/sound.h | 2 + engines/xeen/spells.cpp | 13 +- engines/xeen/spells.h | 1 + engines/xeen/town.cpp | 321 +++++++++++++++++++++++++++++++++++++++++ engines/xeen/town.h | 75 ++++++++++ engines/xeen/xeen.cpp | 3 + engines/xeen/xeen.h | 2 + 16 files changed, 471 insertions(+), 35 deletions(-) create mode 100644 engines/xeen/town.cpp create mode 100644 engines/xeen/town.h (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index f85e19d99f..0126cd6d17 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -780,6 +780,14 @@ void Interface::doFalling() { // TODO } +void Interface::highlightChar(int charId) { + error("TODO: highlightChar"); +} + +void Interface::unhighlightChar() { + error("TODO: unhighlight"); +} + bool Interface::checkMoveDirection(int key) { Map &map = *_vm->_map; Party &party = *_vm->_party; diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 3d8116d03d..ab30654065 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -99,6 +99,10 @@ public: void doFalling(); + void highlightChar(int charId); + + void unhighlightChar(); + void perform(); }; diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 107f9ecf5a..c9ea2589c6 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -4964,7 +4964,7 @@ void InterfaceMap::drawMiniMap() { party._wizardEyeActive = eyeActive; } -void InterfaceMap::drawTownAnim(int v) { +void InterfaceMap::drawTownAnim(bool v) { warning("TODO"); } diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 3ee2c430e9..153abba223 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -114,18 +114,12 @@ protected: bool _charsShooting; bool _thinWall; bool _isAnimReset; - int _batUIFrame; - int _spotDoorsUIFrame; - int _dangerSenseUIFrame; - int _face1UIFrame; - int _face2UIFrame; int _blessedUIFrame; int _powerShieldUIFrame; int _holyBonusUIFrame; int _heroismUIFrame; int _flipUIFrame; bool _flag1; - int _overallFrame; void setMazeBits(); @@ -135,8 +129,6 @@ protected: void drawMiniMap(); - void assembleBorder(); - virtual void setup(); public: OutdoorDrawList _outdoorList; @@ -144,10 +136,14 @@ public: SpriteResource _globalSprites; bool _upDoorText; Common::String _screenText; - int _face1State; - int _face2State; + int _face1State, _face2State; + int _face1UIFrame, _face2UIFrame; + int _spotDoorsUIFrame; + int _dangerSenseUIFrame; byte _tillMove; int _objNumber; + int _overallFrame; + int _batUIFrame; public: InterfaceMap(XeenEngine *vm); @@ -169,7 +165,9 @@ public: void drawOutdoors(); - void drawTownAnim(int v); + void drawTownAnim(bool v); + + void assembleBorder(); }; } // End of namespace Xeen diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index c5348442ec..c9ea03fafb 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -28,6 +28,7 @@ MODULE_OBJS := \ sound.o \ spells.o \ sprites.o \ + town.o \ xeen.o \ xsurface.o diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 0f48073044..9e11a17aa7 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -68,7 +68,7 @@ const char *const OPTIONS_TITLE = const char *const THE_PARTY_NEEDS_REST = "\x0B""012The Party needs rest!"; -const char *const WHO_WILL = "\X03""c\X0B""000\x09""000%s\x0A\x0A" +const char *const WHO_WILL = "\x03""c\x0B""000\x09""000%s\x0A\x0A" "Who will\x0A%s?\x0A\x0B""055F1 - F%d"; const char *const WHATS_THE_PASSWORD = "What's the Password?"; @@ -566,4 +566,23 @@ const int OUTDOOR_DRAWSTRCT_INDEXES[44] = { 93, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120 }; +const int TOWN_MAXES[2][11] = { + { 23, 13, 32, 16, 26, 16, 16, 16, 16, 16, 16 }, + { 26, 19, 48, 27, 26, 37, 16, 16, 16, 16, 16 } +}; + +const char *const TOWN_ACTION_MUSIC[14] = { + "bank.m", "smith.m", "guild.m", "tavern.m", "temple.m", + "grounds.m", "endgame.m", "bank.m", "sf09.m", "guild.m", + "tavern.m", "temple.m", "smith.m", "endgame.m" +}; + +const char *const TOWN_ACTION_SHAPES[4] = { + "bankr", "blck", "gild", "tvrn" +}; + +const int TOWN_ACTION_FILES[2][7] = { + { 3, 2, 4, 2, 4, 2, 1 }, { 5, 3, 7, 5, 4, 6, 1 } +}; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 8537835630..ff192023a3 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -150,6 +150,14 @@ extern const int ARMOR_STRENGTHS[14]; extern const int OUTDOOR_DRAWSTRCT_INDEXES[44]; +extern const int TOWN_MAXES[2][11]; + +extern const char *const TOWN_ACTION_MUSIC[14]; + +extern const char *const TOWN_ACTION_SHAPES[4]; + +extern const int TOWN_ACTION_FILES[2][7]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 665fd0d632..097216523c 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -96,7 +96,7 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) { _treasureGems = 0; _lineNum = 0; _charIndex = 0; - _v2 = false; + _v2 = 0; _nEdamageType = 0; _animCounter = 0; _eventSkipped = false; @@ -123,7 +123,7 @@ bool Scripts::checkEvents() { _whoWill = 0; Mode oldMode = _vm->_mode; Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0); - int items = _treasureItems; + //int items = _treasureItems; if (_treasureGold & _treasureItems) { // TODO @@ -138,7 +138,7 @@ bool Scripts::checkEvents() { // int var4E = 0; _currentPos = party._mazePosition; _charIndex = 1; - _v2 = true; + _v2 = 1; _nEdamageType = 0; // int var40 = -1; @@ -202,7 +202,7 @@ bool Scripts::checkEvents() { w.close(); } - _v2 = true; + _v2 = 1; Common::fill(&_charFX[0], &_charFX[6], 0); return _scriptResult; @@ -490,7 +490,7 @@ void Scripts::cmdSetChar(Common::Array<byte> ¶ms) { _charIndex = _vm->getRandomNumber(1, _vm->_party->_partyCount); } - _v2 = true; + _v2 = 1; cmdNoAction(params); } @@ -515,7 +515,7 @@ void Scripts::cmdSpawn(Common::Array<byte> ¶ms) { } void Scripts::cmdDoTownEvent(Common::Array<byte> ¶ms) { - _scriptResult = doTownEvent(params[0]); + _scriptResult = _vm->_town->townAction(params[0]); _vm->_party->_stepped = true; cmdExit(params); @@ -1271,15 +1271,6 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { } } -bool Scripts::doTownEvent(int actionId) { - if (actionId == 12) - return false; - - - - return false; -} - bool Scripts::copyProtectionCheck() { // Currentl not implemented return true; diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 44290eef47..59f202e461 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -149,7 +149,7 @@ private: int _mirrorId; int _refreshIcons; int _scriptResult; - bool _v2; + int _v2; bool _scriptExecuted; bool _var50; MazeEvent *_event; @@ -223,8 +223,6 @@ private: bool ifProc(int action, uint32 mask, int mode, int charIndex); - bool doTownEvent(int actionId); - bool copyProtectionCheck(); public: int _animCounter; diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index c1215249a9..d38e16b5b9 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -37,6 +37,8 @@ public: void proc2(Common::SeekableReadStream &f); + void loadMusic(const Common::String &name, int v2) {} + void startMusic(int v1); void playSong(Common::SeekableReadStream &f) {} diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 8a5126c381..29c22b1e0b 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -31,10 +31,15 @@ Spells::Spells(XeenEngine *vm) : _vm(vm) { } void Spells::load() { - File f("spells.xen"); - while (f.pos() < f.size()) - _spellNames.push_back(f.readString()); - f.close(); + File f1("spells.xen"); + while (f1.pos() < f1.size()) + _spellNames.push_back(f1.readString()); + f1.close(); + + File f2("mae.xen"); + while (f2.pos() < f2.size()) + _maeNames.push_back(f2.readString()); + f2.close(); } } // End of namespace Xeen diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h index adb957c26a..48c0f9a897 100644 --- a/engines/xeen/spells.h +++ b/engines/xeen/spells.h @@ -37,6 +37,7 @@ private: void load(); public: Common::StringArray _spellNames; + Common::StringArray _maeNames; public: Spells(XeenEngine *vm); }; diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp new file mode 100644 index 0000000000..214454b058 --- /dev/null +++ b/engines/xeen/town.cpp @@ -0,0 +1,321 @@ +/* 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 "xeen/town.h" +#include "xeen/resources.h" +#include "xeen/xeen.h" + +namespace Xeen { + +Town::Town(XeenEngine *vm) : _vm(vm) { + _townMaxId = 0; + _townActionId = 0; + _townCurrent = 0; + _v1 = 0; + _v2 = 0; + Common::fill(&_arr1[0], &_arr1[6], 0); +} + +void Town::loadStrings(const Common::String &name) { + File f(name); + _textStrings.clear(); + while (f.pos() < f.size()) + _textStrings.push_back(f.readString()); + f.close(); +} + +int Town::townAction(int actionId) { + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + bool isDarkCc = _vm->_files->_isDarkCc; + + if (actionId == 12) { + pyramidEvent(); + return 0; + } + + _townMaxId = TOWN_MAXES[_vm->_files->_isDarkCc][actionId]; + _townActionId = actionId; + _townCurrent = 0; + _v1 = 0; + _townPos = Common::Point(8, 8); + intf._overallFrame = 0; + + // This area sets up the GUI buttos and startup sample to play for the + // given town action + Common::String vocName = "hello1.voc"; + clearButtons(); + _icons1.clear(); + _icons2.clear(); + + switch (actionId) { + case 0: + // Bank + _icons1.load("bank.icn"); + _icons2.load("bank2.icn"); + addButton(Common::Rect(234, 108, 259, 128), Common::KEYCODE_d, &_icons1); + addButton(Common::Rect(261, 108, 285, 128), Common::KEYCODE_w, &_icons1); + addButton(Common::Rect(288, 108, 312, 128), Common::KEYCODE_ESCAPE, &_icons1); + intf._overallFrame = 1; + + sound.playSample(nullptr, 0); + vocName = isDarkCc ? "bank1.voc" : "banker.voc"; + break; + + case 1: + // Blacksmith + _icons1.load("esc.icn"); + addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1, true); + addButton(Common::Rect(234, 54, 308, 62), 0, &_icons1, false); + addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_b, &_icons1, false); + addButton(Common::Rect(234, 74, 308, 82), 0, &_icons1, false); + addButton(Common::Rect(234, 84, 308, 92), 0, &_icons1, false); + + sound.playSample(nullptr, 0); + vocName = isDarkCc ? "see2.voc" : "whaddayo.voc"; + break; + + case 2: + // Guild + loadStrings("spldesc.bin"); + _icons1.load("esc.icn"); + addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1, true); + addButton(Common::Rect(234, 54, 308, 62), 0, &_icons1, false); + addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_b, &_icons1, false); + addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_s, &_icons1, false); + addButton(Common::Rect(234, 84, 308, 92), 0, &_icons1, false); + _vm->_mode = MODE_17; + + sound.playSample(nullptr, 0); + vocName = isDarkCc ? "parrot1.voc" : "guild10.voc"; + break; + + case 3: + // Tavern + loadStrings("tavern.bin"); + _icons1.load("tavern.icn"); + addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons1, true); + addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_s, &_icons1, true); + addButton(Common::Rect(234, 54, 308, 62), Common::KEYCODE_d, &_icons1, false); + addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_f, &_icons1, false); + addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_t, &_icons1, false); + addButton(Common::Rect(234, 84, 308, 92), Common::KEYCODE_r, &_icons1, false); + _vm->_mode = MODE_17; + + sound.playSample(nullptr, 0); + vocName = isDarkCc ? "hello1.voc" : "hello.voc"; + break; + + case 4: + // Temple + _icons1.load("esc.icn"); + addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1, true); + addButton(Common::Rect(234, 54, 308, 62), Common::KEYCODE_h, &_icons1, false); + addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_d, &_icons1, false); + addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_u, &_icons1, false); + addButton(Common::Rect(234, 84, 308, 92), 0, &_icons1, false); + + sound.playSample(nullptr, 0); + vocName = isDarkCc ? "help2.voc" : "maywe2.voc"; + break; + + case 5: + // Training + Common::fill(&_arr1[0], &_arr1[6], 0); + _v2 = 0; + + _icons1.load("train.icn"); + addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons1, true); + addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t, &_icons1, false); + + sound.playSample(nullptr, 0); + vocName = isDarkCc ? "training.voc" : "youtrn1.voc"; + break; + + case 6: + // Arena event + arenaEvent(); + return false; + + case 8: + // Reaper event + reaperEvent(); + return false; + + case 9: + // Golem event + golemEvent(); + return false; + + case 10: + case 13: + dwarfEvent(); + return false; + + case 11: + sphinxEvent(); + return false; + + default: + break; + } + + sound.loadMusic(TOWN_ACTION_MUSIC[actionId], 223); + + _townSprites.clear(); + for (int idx = 0; idx < TOWN_ACTION_FILES[isDarkCc][actionId]; ++idx) { + Common::String shapesName = Common::String::format("%s%d.twn", + TOWN_ACTION_SHAPES[actionId], idx + 1); + _townSprites[idx].load(shapesName); + } + + Common::String title = createTownText(); + intf._face1UIFrame = intf._face2UIFrame = 0; + intf._dangerSenseUIFrame = 0; + intf._spotDoorsUIFrame = 0; + intf._batUIFrame = 0; + + _townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos); + if (actionId == 0 && isDarkCc) { + _townSprites[4].draw(screen, _vm->getRandomNumber(13, 18), + Common::Point(8, 30)); + } + + intf.assembleBorder(); + + // Open up the window and write the string + screen._windows[10].open(); + screen._windows[10].writeString(title); + drawButtons(&screen); + + screen._windows[0].update(); + intf.highlightChar(0); + intf.drawTownAnim(1); + + if (actionId == 0) + intf._overallFrame = 2; + + File voc(vocName); + sound.playSample(&voc, 1); + + do { + townWait(); + doTownOptions(); + screen._windows[10].writeString(title); + drawButtons(&screen); + } while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE); + + switch (actionId) { + case 1: + // Leave blacksmith + if (isDarkCc) { + sound.playSample(nullptr, 0); + File f("come1.voc"); + sound.playSample(&f, 1); + } + break; + + case 3: { + // Leave Tavern + sound.playSample(nullptr, 0); + File f(isDarkCc ? "gdluck1.voc" : "goodbye.voc"); + sound.playSample(&f, 1); + + map.mazeData()._mazeNumber = party._mazeId; + break; + } + default: + break; + } + + int result; + if (party._mazeId != 0) { + map.load(party._mazeId); + _v1 += 1440; + party.addTime(_v1); + result = 0; + } else { + _vm->_saves->saveChars(); + result = 2; + } + + for (uint idx = 0; idx < _townSprites.size(); ++idx) + _townSprites[idx].clear(); + intf.mainIconsPrint(); + _buttonValue = 0; + + return result; +} + +void Town::townWait() { + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + + while (!_vm->shouldQuit()) { + events.updateGameCounter(); + while (!_vm->shouldQuit() && !_buttonValue && events.timeElapsed() < 3) { + checkEvents(_vm); + } + if (_buttonValue) + return; + + intf.drawTownAnim(!_vm->_screen->_windows[11]._enabled); + } +} + +void Town::pyramidEvent() { + error("TODO: pyramidEvent"); +} + +void Town::arenaEvent() { + error("TODO: arenaEvent"); +} + +void Town::reaperEvent() { + error("TODO: repearEvent"); +} + +void Town::golemEvent() { + error("TODO: golemEvent"); +} + +void Town::sphinxEvent() { + error("TODO: sphinxEvent"); +} + +void Town::dwarfEvent() { + error("TODO: dwarfEvent"); +} + +Common::String Town::createTownText() { + error("TODO"); +} + +void Town::doTownOptions() { + error("TODO: doTownOptions"); +} + + +} // End of namespace Xeen diff --git a/engines/xeen/town.h b/engines/xeen/town.h new file mode 100644 index 0000000000..2221ed5400 --- /dev/null +++ b/engines/xeen/town.h @@ -0,0 +1,75 @@ +/* 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 XEEN_TOWN_H +#define XEEN_TOWN_H + +#include "common/scummsys.h" +#include "common/str-array.h" +#include "xeen/dialogs.h" + +namespace Xeen { + +class XeenEngine; + +class Town: public ButtonContainer { +private: + XeenEngine *_vm; + SpriteResource _icons1, _icons2; + Common::StringArray _textStrings; + Common::Array<SpriteResource> _townSprites; + int _townMaxId; + int _townActionId; + int _townCurrent; + int _v1; + int _v2; + Common::Point _townPos; + int _arr1[6]; + + void loadStrings(const Common::String &name); + + void pyramidEvent(); + + void arenaEvent(); + + void reaperEvent(); + + void golemEvent(); + + void sphinxEvent(); + + void dwarfEvent(); + + Common::String createTownText(); + + void townWait(); + + void doTownOptions(); +public: + Town(XeenEngine *vm); + + int townAction(int actionId); +}; + +} // End of namespace Xeen + +#endif /* XEEN_SPELLS_H */ diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 8879b15a0d..8d646fbcf5 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -48,6 +48,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _scripts = nullptr; _sound = nullptr; _spells = nullptr; + _town = nullptr; _eventData = nullptr; _dangerSenseAllowed = false; _noDirectionSense = false; @@ -69,6 +70,7 @@ XeenEngine::~XeenEngine() { delete _scripts; delete _sound; delete _spells; + delete _town; delete _eventData; delete _files; } @@ -94,6 +96,7 @@ void XeenEngine::initialize() { _screen->setupWindows(); _sound = new SoundManager(this); _spells = new Spells(this); + _town = new Town(this); File f("029.obj"); _eventData = f.readStream(f.size()); diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 38c7beb057..1145072d6d 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -44,6 +44,7 @@ #include "xeen/scripts.h" #include "xeen/sound.h" #include "xeen/spells.h" +#include "xeen/town.h" /** * This is the namespace of the Xeen engine. @@ -142,6 +143,7 @@ public: Scripts *_scripts; SoundManager *_sound; Spells *_spells; + Town *_town; Treasure _treasure; Mode _mode; GameEvent _gameEvent; -- cgit v1.2.3 From 81e1bd2930bf4192fa8bfdbb805c65795e68c6e1 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 26 Jan 2015 21:35:50 -0500 Subject: XEEN: Implemented createTownText --- engines/xeen/party.cpp | 59 ++++++++++++++++ engines/xeen/party.h | 8 +++ engines/xeen/resources.cpp | 64 +++++++++++++++++ engines/xeen/resources.h | 24 +++++++ engines/xeen/town.cpp | 172 +++++++++++++++++++++++++++++++++++++++++++-- engines/xeen/town.h | 18 +++-- engines/xeen/xeen.cpp | 10 +++ engines/xeen/xeen.h | 4 ++ 8 files changed, 349 insertions(+), 10 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 388b8de261..1baa25404f 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -757,6 +757,65 @@ void Character::setValue(int id, uint value) { } } +bool Character::guildMember() const { + Party &party = *Party::_vm->_party; + + if (party._mazeId == 49 && !Party::_vm->_files->_isDarkCc) { + return hasAward(5); + } + + switch (party._mazeId) { + case 29: + return hasAward(83); + case 31: + return hasAward(84); + case 33: + return hasAward(85); + case 35: + return hasAward(86); + default: + return hasAward(87); + } +} + +uint Character::nextExperienceLevel() const { + uint base = currentExperienceLevel(); + uint curr = getCurrentExperience(); + return (curr < base) ? 0 : curr - base; +} + +uint Character::currentExperienceLevel() const { + int shift, base; + if (_level._permanent >= 12) { + base = _level._permanent - 12; + shift = 10; + } else { + base = 0; + shift = _level._permanent; + } + + return (base * 1024000) + (CLASS_EXP_LEVELS[_class] << shift); +} + +uint Character::getCurrentExperience() const { + int lev = _level._permanent - 1; + int shift, base; + + if (lev > 0 && lev < 12) + return _experience; + + if (lev >= 12) { + base = lev - 12; + shift = 10; + } else { + base = 0; + shift = lev - 1; + } + + return (base * 1024000) + (CLASS_EXP_LEVELS[_class] << shift) + + _experience; +} + /*------------------------------------------------------------------------*/ void Roster::synchronize(Common::Serializer &s) { diff --git a/engines/xeen/party.h b/engines/xeen/party.h index c77364bd10..0b7572cccf 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -167,6 +167,14 @@ public: int itemScan(int itemId) const; void setValue(int id, uint value); + + bool guildMember() const; + + uint nextExperienceLevel() const; + + uint currentExperienceLevel() const; + + uint getCurrentExperience() const; }; class Roster: public Common::Array<Character> { diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 9e11a17aa7..c1951d704c 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -290,6 +290,10 @@ const char *const CLASS_NAMES[11] = { "Ninja", "Barbarian", "Druid", "Ranger", nullptr }; +const uint CLASS_EXP_LEVELS[10] = { + 1500, 2000, 2000, 1500, 2000, 1000, 1500, 1500, 1500, 2000 +}; + const char *const CONDITION_NAMES[18] = { nullptr, "Cursed", "Heart Broken", "Weak", "Poisoned", "Diseased", "Insane", "In Love", "Drunk", "Asleep", "Depressed", "Confused", @@ -585,4 +589,64 @@ const int TOWN_ACTION_FILES[2][7] = { { 3, 2, 4, 2, 4, 2, 1 }, { 5, 3, 7, 5, 4, 6, 1 } }; +const char *const BANK_TEXT = "\x0D\x02\x03""c\x0B""122\x09""013" + "\x0C""37D\x0C""dep\x09""040\x0C""37W\x0C""dith\x09""067ESC" + "\x01\x09""000\x0B""000Bank of Xeen\x0B""015\n" + "Bank\x03l\n" + "Gold\x03r\x09""000%s\x03l\n" + "Gems\x03r\x09""000%s\x03""c\n" + "\n" + "Party\x03l\n" + "Gold\x03r\x09""000%s\x03l\n" + "Gems\x03r\x09""000%s"; + +const char *const BLACKSMITH_TEXT = "\x01\x0D\x03""c\x0B""000\x09""000" + "Store Options for\x09""039\x0B""027%s\x03""l\x0B""046\n" + "\x09""011\x0C""37B\x0C""drowse\n" + "\x09""000\x0B""090Gold\x03r\x09""000%s" + "\x02\x03""c\x0B""122\x09""040ESC\x01"; + +const char *const GUILD_NOT_MEMBER_TEXT = + "\n\nYou have to be a member to shop here."; + +const char *const GUILD_TEXT = "\x03""c\x0B""027\x09""039%s" + "\x03l\x0B""046\n" + "\x09""012\x0C""37B\x0C""duy Spells\n" + "\x09""012\x0C""37S\x0C""dpell Info"; + +const char *const TAVERN_TEXT = + "\x0D\x03""c\x0B""000\x09""000Tavern Options for\x09""039" + "\x0B""027%s%s\x03l\x09""000" + "\x0B""090Gold\x03r\x09""000%s\x02\x03""c\x0B""122" + "\x09""021\x0C""37S\x0C""dign in\x09""060ESC\x01"; + +const char *const FOOD_AND_DRINK = + "\x03l\x09""017\x0B""046\x0C""37D\x0C""drink\n" + "\x09""017\x0C""37F\x0C""dood\n" + "\x09""017\x0C""37T\x0C""dip\n" + "\x09""017\x0C""37R\x0C""dumors"; + +const char *const TEMPLE_TEXT = + "\x0D\x03""c\x0B""000\x09""000Temple Options for" + "\x09""039\x0B""027%s\x03l\x09""000\x0B""046" + "\x0C""37H\x0C""deal\x03r\x09""000%lu\x03l\n" + "\x0C""37D\x0C""donation\x03r\x09""000%lu\x03l\n" + "\x0C""37U\x0C""dnCurse\x03r\x09""000%s" + "\x03l\x09""000\x0B""090Gold\x03r\x09""000%s" + "\x02\x03""c\x0B""122\x09""040ESC\x01"; + +const char *const EXPERIENCE_FOR_LEVEL = + "%s needs %lu experience for level %u."; + +const char *const LEARNED_ALL = "%s has learned all we can teach!"; + +const char *const ELIGIBLE_FOR_LEVEL = "%s is eligible for level %d."; + +const char *const TRAINING_TEXT = + "\x0D\x03""cTraining Options\n" + "\n" + "%s\x03l\x0B""090\x09""000Gold\x03r\x09" + "000%s\x02\x03""c\x0B""122\x09""021" + "\x0C""37T\x0C""drain\x09""060ESC\x01"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index ff192023a3..a6f52cb50e 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -66,6 +66,8 @@ extern const int RACE_SP_BONUSES[5][2]; extern const char *const CLASS_NAMES[11]; +extern const uint CLASS_EXP_LEVELS[10]; + extern const char *const ALIGNMENT_NAMES[3]; extern const char *const SEX_NAMES[2]; @@ -158,6 +160,28 @@ extern const char *const TOWN_ACTION_SHAPES[4]; extern const int TOWN_ACTION_FILES[2][7]; +extern const char *const BANK_TEXT; + +extern const char *const BLACKSMITH_TEXT; + +extern const char *const GUILD_NOT_MEMBER_TEXT; + +extern const char *const GUILD_TEXT; + +extern const char *const TAVERN_TEXT; + +extern const char *const FOOD_AND_DRINK; + +extern const char *const TEMPLE_TEXT; + +extern const char *const EXPERIENCE_FOR_LEVEL; + +extern const char *const LEARNED_ALL; + +extern const char *const ELIGIBLE_FOR_LEVEL; + +extern const char *const TRAINING_TEXT; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 214454b058..bb8590fc48 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -27,12 +27,23 @@ namespace Xeen { Town::Town(XeenEngine *vm) : _vm(vm) { + Common::fill(&_arr1[0], &_arr1[6], 0); _townMaxId = 0; _townActionId = 0; _townCurrent = 0; + _currentCharLevel = 0; _v1 = 0; _v2 = 0; - Common::fill(&_arr1[0], &_arr1[6], 0); + _donation = 0; + _healCost = 0; + _v5 = _v6 = 0; + _v10 = _v11 = 0; + _v12 = _v13 = 0; + _v14 = 0; + _v20 = 0; + _uncurseCost = 0; + _flag1 = false; + _nextExperienceLevel = 0; } void Town::loadStrings(const Common::String &name) { @@ -191,7 +202,8 @@ int Town::townAction(int actionId) { _townSprites[idx].load(shapesName); } - Common::String title = createTownText(); + Character *charP = &party._activeParty[0]; + Common::String title = createTownText(*charP); intf._face1UIFrame = intf._face2UIFrame = 0; intf._dangerSenseUIFrame = 0; intf._spotDoorsUIFrame = 0; @@ -222,7 +234,7 @@ int Town::townAction(int actionId) { do { townWait(); - doTownOptions(); + charP = doTownOptions(charP); screen._windows[10].writeString(title); drawButtons(&screen); } while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE); @@ -309,11 +321,159 @@ void Town::dwarfEvent() { error("TODO: dwarfEvent"); } -Common::String Town::createTownText() { - error("TODO"); +Common::String Town::createTownText(Character &ch) { + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + Common::String msg; + + switch (_townActionId) { + case 0: + // Bank + return Common::String::format(BANK_TEXT, + XeenEngine::printMil(party._bankGold).c_str(), + XeenEngine::printMil(party._bankGems).c_str(), + XeenEngine::printMil(party._gold).c_str(), + XeenEngine::printMil(party._gems).c_str()); + case 1: + // Blacksmith + return Common::String::format(BLACKSMITH_TEXT, + XeenEngine::printMil(party._gold)); + + case 2: + // Guild + return !ch.guildMember() ? GUILD_NOT_MEMBER_TEXT : + Common::String::format(GUILD_TEXT, ch._name.c_str()); + + case 3: + // Tavern + return Common::String::format(TAVERN_TEXT, ch._name, + FOOD_AND_DRINK, XeenEngine::printMil(party._gold).c_str()); + + case 4: + // Temple + _donation = 0; + _uncurseCost = 0; + _v5 = 0; + _v6 = 0; + _healCost = 0; + + if (party._mazeId == (_vm->_files->_isDarkCc ? 29 : 28)) { + _v10 = _v11 = _v12 = _v13 = 0; + _v14 = 10; + } else if (party._mazeId == (_vm->_files->_isDarkCc ? 31 : 30)) { + _v13 = 10; + _v12 = 50; + _v11 = 500; + _v10 = 100; + _v14 = 25; + } else if (party._mazeId == (_vm->_files->_isDarkCc ? 37 : 73)) { + _v13 = 20; + _v12 = 100; + _v11 = 1000; + _v10 = 200; + _v14 = 50; + } else if (_vm->_files->_isDarkCc || party._mazeId == 49) { + _v13 = 100; + _v12 = 500; + _v11 = 5000; + _v10 = 300; + _v14 = 100; + } + + _currentCharLevel = ch.getCurrentLevel(); + if (ch._currentHp < ch.getMaxHP()) { + _healCost = _currentCharLevel * 10 + _v13; + } + + for (int attrib = HEART_BROKEN; attrib <= UNCONSCIOUS; ++attrib) { + if (ch._conditions[attrib]) + _healCost += _currentCharLevel * 10; + } + + _v6 = 0; + if (ch._conditions[DEAD]) { + _v6 += (_currentCharLevel * 100) + (ch._conditions[DEAD] * 50) + _v12; + } + if (ch._conditions[STONED]) { + _v6 += (_currentCharLevel * 100) + (ch._conditions[STONED] * 50) + _v12; + } + if (ch._conditions[ERADICATED]) { + _v5 = (_currentCharLevel * 1000) + (ch._conditions[ERADICATED] * 500) + _v11; + } + + for (int idx = 0; idx < 9; ++idx) { + _uncurseCost |= ch._weapons[idx]._bonusFlags & 0x40; + _uncurseCost |= ch._armor[idx]._bonusFlags & 0x40; + _uncurseCost |= ch._accessories[idx]._bonusFlags & 0x40; + _uncurseCost |= ch._misc[idx]._bonusFlags & 0x40; + } + + if (_uncurseCost || ch._conditions[CURSED]) + _v5 = (_currentCharLevel * 20) + _v10; + + _donation = _flag1 ? 0 : _v14; + _healCost += _v6 + _v5; + + return Common::String::format(TEMPLE_TEXT, ch._name.c_str(), + _healCost, _donation, XeenEngine::printK(_uncurseCost).c_str(), + XeenEngine::printMil(party._gold).c_str()); + + case 5: + // Training + if (_vm->_files->_isDarkCc) { + switch (party._mazeId) { + case 29: + _v20 = 30; + break; + case 31: + _v20 = 50; + break; + case 37: + _v20 = 200; + break; + default: + _v20 = 100; + break; + } + } else { + switch (party._mazeId) { + case 28: + _v20 = 10; + break; + case 30: + _v20 = 15; + break; + default: + _v20 = 20; + break; + } + } + + _nextExperienceLevel = ch.nextExperienceLevel(); + + if (_nextExperienceLevel >= 0x10000 && ch._level._permanent < _v20) { + int nextLevel = ch._level._permanent + 1; + return Common::String::format(EXPERIENCE_FOR_LEVEL, + ch._name.c_str(), _nextExperienceLevel, nextLevel); + } else if (ch._level._permanent >= 20) { + _nextExperienceLevel = 1; + msg = Common::String::format(LEARNED_ALL, ch._name.c_str()); + } else { + msg = Common::String::format(ELIGIBLE_FOR_LEVEL, + ch._name.c_str(), ch._level._permanent + 1); + } + + return Common::String::format(TRAINING_TEXT, + XeenEngine::printMil(party._gold).c_str()); + + default: + return ""; + } } -void Town::doTownOptions() { +Character *Town::doTownOptions(Character *charP) { + Common::String result; + error("TODO: doTownOptions"); } diff --git a/engines/xeen/town.h b/engines/xeen/town.h index 2221ed5400..07e9badc46 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/str-array.h" #include "xeen/dialogs.h" +#include "xeen/party.h" namespace Xeen { @@ -40,10 +41,19 @@ private: int _townMaxId; int _townActionId; int _townCurrent; - int _v1; - int _v2; + int _v1, _v2; + int _donation; + int _healCost; + int _v5, _v6; + int _v10, _v11, _v12; + int _v13, _v14; + int _v20; + int _uncurseCost; Common::Point _townPos; int _arr1[6]; + int _currentCharLevel; + bool _flag1; + uint _nextExperienceLevel; void loadStrings(const Common::String &name); @@ -59,11 +69,11 @@ private: void dwarfEvent(); - Common::String createTownText(); + Common::String createTownText(Character &ch); void townWait(); - void doTownOptions(); + Character *doTownOptions(Character *charP); public: Town(XeenEngine *vm); diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 8d646fbcf5..d7a85fbbf8 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -339,4 +339,14 @@ void XeenEngine::gameLoop() { } } +Common::String XeenEngine::printMil(uint value) { + return (value >= 1000000) ? Common::String::format("%lu mil", value / 1000000) : + Common::String::format("%lu", value); +} + +Common::String XeenEngine::printK(uint value) { + return (value > 9999) ? Common::String::format("%uk", value / 1000) : + Common::String::format("%u", value); +} + } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 1145072d6d..cb09c280cd 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -198,6 +198,10 @@ public: * Write out a savegame header */ void writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeader &header); + + static Common::String printMil(uint value); + + static Common::String printK(uint value); }; } // End of namespace Xeen -- cgit v1.2.3 From 88382b2d8f0f1fd27e2100a94ace74453d6186f7 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 27 Jan 2015 08:02:54 -0500 Subject: XEEN: Added NumericInput class and refactored existing string input --- engines/xeen/dialogs_input.cpp | 187 ++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_input.h | 66 ++++++++++++ engines/xeen/dialogs_string_input.cpp | 82 --------------- engines/xeen/dialogs_string_input.h | 45 -------- engines/xeen/module.mk | 2 +- engines/xeen/resources.cpp | 27 +++++ engines/xeen/resources.h | 16 +++ engines/xeen/screen.cpp | 76 -------------- engines/xeen/screen.h | 2 - engines/xeen/scripts.cpp | 2 +- engines/xeen/town.cpp | 108 ++++++++++++++++++-- engines/xeen/town.h | 9 +- 12 files changed, 402 insertions(+), 220 deletions(-) create mode 100644 engines/xeen/dialogs_input.cpp create mode 100644 engines/xeen/dialogs_input.h delete mode 100644 engines/xeen/dialogs_string_input.cpp delete mode 100644 engines/xeen/dialogs_string_input.h (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_input.cpp b/engines/xeen/dialogs_input.cpp new file mode 100644 index 0000000000..1394379910 --- /dev/null +++ b/engines/xeen/dialogs_input.cpp @@ -0,0 +1,187 @@ +/* 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 "xeen/dialogs_input.h" +#include "xeen/scripts.h" +#include "xeen/xeen.h" + +namespace Xeen { + +/** + * Allows the user to enter a string + */ +int Input::getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric) { + _vm->_noDirectionSense = true; + Common::String msg = Common::String::format("\x03""l\t000\x04%03d\x03""c", maxWidth); + _window->writeString(msg); + _window->update(); + + while (!_vm->shouldQuit()) { + Common::KeyCode keyCode = doCursor(msg); + + if ((keyCode == Common::KEYCODE_BACKSPACE || keyCode == Common::KEYCODE_DELETE) + && line.size() > 0) + line.deleteLastChar(); + else if (line.size() < maxLen && (line.size() > 0 || keyCode != Common::KEYCODE_SPACE) + && ((isNumeric && keyCode >= Common::KEYCODE_0 && keyCode < Common::KEYCODE_9) || + (!isNumeric && keyCode >= Common::KEYCODE_SPACE && keyCode < Common::KEYCODE_DELETE))) { + line += (char)keyCode; + } else if (keyCode == Common::KEYCODE_RETURN || keyCode == Common::KEYCODE_KP_ENTER) { + break; + } else if (keyCode == Common::KEYCODE_ESCAPE) { + line = ""; + break; + } + } + + _vm->_noDirectionSense = false; + return line.size(); +} + +/** + * Draws the cursor and waits until the user presses a key + */ +Common::KeyCode Input::doCursor(const Common::String &msg) { + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Screen &screen = *_vm->_screen; + + bool oldUpDoorText = intf._upDoorText; + byte oldTillMove = intf._tillMove; + intf._upDoorText = false; + intf._tillMove = 0; + + bool flag = !_vm->_startupWindowActive && !screen._windows[25]._enabled + && _vm->_mode != MODE_FF && _vm->_mode != MODE_17; + + Common::KeyCode ch = Common::KEYCODE_INVALID; + while (!_vm->shouldQuit()) { + events.updateGameCounter(); + + if (flag) + intf.draw3d(false); + _window->writeString(msg); + _window->update(); + + if (flag) + screen._windows[3].update(); + + events.wait(1, true); + if (events.isKeyPending()) { + Common::KeyState keyState; + events.getKey(keyState); + ch = keyState.keycode; + break; + } + } + + _window->writeString(""); + _window->update(); + + intf._tillMove = oldTillMove; + intf._upDoorText = oldUpDoorText; + + return ch; +} + +/*------------------------------------------------------------------------*/ + +StringInput::StringInput(XeenEngine *vm): Input(vm, &vm->_screen->_windows[6]) { +} + +int StringInput::show(XeenEngine *vm, bool type, const Common::String &msg1, + const Common::String &msg2, int opcode) { + StringInput *dlg = new StringInput(vm); + int result = dlg->execute(type, msg1, msg2, opcode); + delete dlg; + + return result; +} + +int StringInput::execute(bool type, const Common::String &expected, + const Common::String &title, int opcode) { + Interface &intf = *_vm->_interface; + Screen &screen = *_vm->_screen; + Scripts &scripts = *_vm->_scripts; + Window &w = screen._windows[6]; + SoundManager &sound = *_vm->_sound; + int result = 0; + + w.open(); + w.writeString(Common::String::format("\r\x03""c%s\v024\t000", title.c_str())); + w.update(); + + Common::String line; + if (getString(line, 30, 200, false)) { + if (type) { + if (line == intf._interfaceText) { + result = true; + } else if (line == expected) { + result = (opcode == 55) ? -1 : 1; + } + } else { + // Load in the mirror list + File f(Common::String::format("%smirr.txt", + _vm->_files->_isDarkCc ? "dark" : "xeen")); + MirrorEntry me; + scripts._mirror.clear(); + while (me.synchronize(f)) + scripts._mirror.push_back(me); + + for (uint idx = 0; idx < scripts._mirror.size(); ++idx) { + if (line == scripts._mirror[idx]._name) { + result = idx; + sound.playFX(_vm->_files->_isDarkCc ? 35 : 61); + break; + } + } + } + } + + w.close(); + return result; +} + +/*------------------------------------------------------------------------*/ + +NumericInput::NumericInput(XeenEngine *vm, int window) : Input(vm, &vm->_screen->_windows[window]) { +} + +int NumericInput::show(XeenEngine *vm, int window, int maxLength, int maxWidth) { + NumericInput *dlg = new NumericInput(vm, window); + int result = dlg->execute(maxLength, maxWidth); + delete dlg; + + return result; +} + +int NumericInput::execute(int maxLength, int maxWidth) { + Common::String line; + + if (getString(line, maxLength, maxWidth, true)) + return atoi(line.c_str()); + else + return 0; +} + + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_input.h b/engines/xeen/dialogs_input.h new file mode 100644 index 0000000000..c6d832ce6b --- /dev/null +++ b/engines/xeen/dialogs_input.h @@ -0,0 +1,66 @@ +/* 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 XEEN_DIALOGS_STRING_INPUT_H +#define XEEN_DIALOGS_STRING_INPUT_H + +#include "common/keyboard.h" +#include "xeen/dialogs.h" +#include "xeen/screen.h" + +namespace Xeen { + +class Input : public ButtonContainer { +private: + Common::KeyCode doCursor(const Common::String &msg); +protected: + XeenEngine *_vm; + Window *_window; + + int getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric); + + Input(XeenEngine *vm, Window *window) : _vm(vm), _window(window) {} +}; + +class StringInput : public Input { +protected: + StringInput(XeenEngine *vm); + + int execute(bool type, const Common::String &expected, + const Common::String &title, int opcode); +public: + static int show(XeenEngine *vm, bool type, const Common::String &msg1, + const Common::String &msg2, int opcode); +}; + +class NumericInput : public Input { +private: + NumericInput(XeenEngine *vm, int window); + + int execute(int maxLength, int maxWidth); +public: + static int show(XeenEngine *vm, int window, int maxLength, int maxWidth); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_STRING_INPUT_H */ diff --git a/engines/xeen/dialogs_string_input.cpp b/engines/xeen/dialogs_string_input.cpp deleted file mode 100644 index ced4ad39ff..0000000000 --- a/engines/xeen/dialogs_string_input.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* 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 "xeen/dialogs_string_input.h" -#include "xeen/scripts.h" -#include "xeen/xeen.h" - -namespace Xeen { - -int StringInput::show(XeenEngine *vm, bool type, const Common::String &msg1, - const Common::String &msg2, int opcdoe) { - StringInput *dlg = new StringInput(vm); - int result = dlg->execute(type, msg1, msg2, opcdoe); - delete dlg; - - return result; -} - -int StringInput::execute(bool type, const Common::String &expected, - const Common::String &title, int opcode) { - Interface &intf = *_vm->_interface; - Screen &screen = *_vm->_screen; - Scripts &scripts = *_vm->_scripts; - Window &w = screen._windows[6]; - SoundManager &sound = *_vm->_sound; - int result = 0; - - w.open(); - w.writeString(Common::String::format("\r\x03""c%s\v024\t000", title.c_str())); - w.update(); - - Common::String line; - if (w.getString(line, 30, 200)) { - if (type) { - if (line == intf._interfaceText) { - result = true; - } else if (line == expected) { - result = (opcode == 55) ? -1 : 1; - } - } else { - // Load in the mirror list - File f(Common::String::format("%smirr.txt", - _vm->_files->_isDarkCc ? "dark" : "xeen")); - MirrorEntry me; - scripts._mirror.clear(); - while (me.synchronize(f)) - scripts._mirror.push_back(me); - - for (uint idx = 0; idx < scripts._mirror.size(); ++idx) { - if (line == scripts._mirror[idx]._name) { - result = idx; - sound.playFX(_vm->_files->_isDarkCc ? 35 : 61); - break; - } - } - } - } - - w.close(); - return result; -} - -} // End of namespace Xeen diff --git a/engines/xeen/dialogs_string_input.h b/engines/xeen/dialogs_string_input.h deleted file mode 100644 index 1e18726ff2..0000000000 --- a/engines/xeen/dialogs_string_input.h +++ /dev/null @@ -1,45 +0,0 @@ -/* 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 XEEN_DIALOGS_STRING_INPUT_H -#define XEEN_DIALOGS_STRING_INPUT_H - -#include "xeen/dialogs.h" - -namespace Xeen { - -class StringInput : public ButtonContainer { -private: - XeenEngine *_vm; - - StringInput(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} - - int execute(bool type, const Common::String &expected, - const Common::String &title, int opcode); -public: - static int show(XeenEngine *vm, bool type, const Common::String &msg1, - const Common::String &msg2, int opcdoe); -}; - -} // End of namespace Xeen - -#endif /* XEEN_DIALOGS_STRING_INPUT_H */ diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index c9ea03fafb..c361c472cf 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -10,7 +10,7 @@ MODULE_OBJS := \ dialogs.o \ dialogs_error.o \ dialogs_options.o \ - dialogs_string_input.o \ + dialogs_input.o \ dialogs_whowill.o \ dialogs_yesno.o \ events.o \ diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index c1951d704c..cab6e2643d 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -649,4 +649,31 @@ const char *const TRAINING_TEXT = "000%s\x02\x03""c\x0B""122\x09""021" "\x0C""37T\x0C""drain\x09""060ESC\x01"; +const char *const GOLD_GEMS = + "\x03""c\x0B""000\x09""000%s\x03l\n" + "\n" + "Gold\x03r\x09""000%s\x03l\n" + "Gems\x03r\x09""000%s\x02\x03""c\x0B""096\x09""013G" + "\x0C""37o\x0C""dld\x09""040G\x0C\x03""7e" + "\x0C""dms\x09""067ESC\x01"; + +const char *const DEPOSIT_WITHDRAWL[2] = { "Deposit", "Withdrawl" }; + +const char *const NOT_ENOUGH_X_IN_THE_Y = + "\x03""c\x0B""012Not enough %s in the %s!\x03l"; + +const char *const NO_X_IN_THE_Y = "\x03""c\x0B""012No %s in the %s!\x03l"; + +const char *const STAT_NAMES[16] = { + "Might", "Intellect", "Personality", "Endurance", "Speed", + "Accuracy", "Luck", "Age", "Level", "Armor Class", "Hit Points", + "Spell Points", "Resistances", "Skills", "Awards", "Experience" +}; + +const char *const CONSUMABLE_NAMES[4] = { "Gold", "Gems", "Food", "Condition" }; + +const char *const WHERE_NAMES[2] = { "Party", "Bank" }; + +const char *const AMOUNT = "\x03""c\x09""000\x0B""051Amount\x03l\n"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index a6f52cb50e..7461888c05 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -182,6 +182,22 @@ extern const char *const ELIGIBLE_FOR_LEVEL; extern const char *const TRAINING_TEXT; +extern const char *const GOLD_GEMS; + +extern const char *const DEPOSIT_WITHDRAWL[2]; + +extern const char *const NOT_ENOUGH_X_IN_THE_Y; + +extern const char *const NO_X_IN_THE_Y; + +extern const char *const STAT_NAMES[16]; + +extern const char *const CONSUMABLE_NAMES[4]; + +extern const char *const WHERE_NAMES[2]; + +extern const char *const AMOUNT; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 5088829cf6..87062dc5ec 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -177,82 +177,6 @@ void Window::drawList(DrawStruct *items, int count) { } } -/** - * Allows the user to enter a string - */ -int Window::getString(Common::String &line, uint maxLen, int maxWidth) { - _vm->_noDirectionSense = true; - Common::String msg = Common::String::format("\x03""l\t000\x04%03d\x03""c", maxWidth); - writeString(msg); - update(); - - while (!_vm->shouldQuit()) { - Common::KeyCode keyCode = doCursor(msg); - - if ((keyCode == Common::KEYCODE_BACKSPACE || keyCode == Common::KEYCODE_DELETE) - && line.size() > 0) - line.deleteLastChar(); - else if (keyCode >= Common::KEYCODE_SPACE && keyCode < Common::KEYCODE_DELETE - && line.size() < maxLen && (line.size() > 0 || keyCode != Common::KEYCODE_SPACE)) { - - } else if (keyCode == Common::KEYCODE_RETURN || keyCode == Common::KEYCODE_KP_ENTER) { - break; - } else if (keyCode == Common::KEYCODE_ESCAPE) { - line = ""; - break; - } - } - - _vm->_noDirectionSense = false; - return line.size(); -} - -/** - * Draws the cursor and waits until the user presses a key - */ -Common::KeyCode Window::doCursor(const Common::String &msg) { - EventsManager &events = *_vm->_events; - Interface &intf = *_vm->_interface; - Screen &screen = *_vm->_screen; - - bool oldUpDoorText = intf._upDoorText; - byte oldTillMove = intf._tillMove; - intf._upDoorText = false; - intf._tillMove = 0; - - bool flag = !_vm->_startupWindowActive && !screen._windows[25]._enabled - && _vm->_mode != MODE_FF && _vm->_mode != MODE_17; - - Common::KeyCode ch = Common::KEYCODE_INVALID; - while (!_vm->shouldQuit()) { - events.updateGameCounter(); - - if (flag) - intf.draw3d(false); - writeString(msg); - update(); - - if (flag) - screen._windows[3].update(); - - events.wait(1, true); - if (events.isKeyPending()) { - Common::KeyState keyState; - events.getKey(keyState); - ch = keyState.keycode; - break; - } - } - - writeString(""); - update(); - - intf._tillMove = oldTillMove; - intf._upDoorText = oldUpDoorText; - - return ch; -} - /*------------------------------------------------------------------------*/ /** diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 6e805c2aa3..85affe3aa2 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -67,8 +67,6 @@ private: int _ycL, _ycH; void open2(); - - Common::KeyCode doCursor(const Common::String &msg); public: bool _enabled; public: diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 097216523c..e3cc682069 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -21,7 +21,7 @@ */ #include "xeen/scripts.h" -#include "xeen/dialogs_string_input.h" +#include "xeen/dialogs_input.h" #include "xeen/dialogs_whowill.h" #include "xeen/dialogs_yesno.h" #include "xeen/party.h" diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index bb8590fc48..dceb79c354 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -195,8 +195,8 @@ int Town::townAction(int actionId) { sound.loadMusic(TOWN_ACTION_MUSIC[actionId], 223); - _townSprites.clear(); - for (int idx = 0; idx < TOWN_ACTION_FILES[isDarkCc][actionId]; ++idx) { + _townSprites.resize(TOWN_ACTION_FILES[isDarkCc][actionId]); + for (uint idx = 0; idx < _townSprites.size(); ++idx) { Common::String shapesName = Common::String::format("%s%d.twn", TOWN_ACTION_SHAPES[actionId], idx + 1); _townSprites[idx].load(shapesName); @@ -281,20 +281,20 @@ int Town::townAction(int actionId) { return result; } -void Town::townWait() { +int Town::townWait() { EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; - while (!_vm->shouldQuit()) { + while (!_vm->shouldQuit() && !_buttonValue) { events.updateGameCounter(); while (!_vm->shouldQuit() && !_buttonValue && events.timeElapsed() < 3) { checkEvents(_vm); } - if (_buttonValue) - return; - - intf.drawTownAnim(!_vm->_screen->_windows[11]._enabled); + if (!_buttonValue) + intf.drawTownAnim(!_vm->_screen->_windows[11]._enabled); } + + return _buttonValue; } void Town::pyramidEvent() { @@ -471,10 +471,96 @@ Common::String Town::createTownText(Character &ch) { } } -Character *Town::doTownOptions(Character *charP) { - Common::String result; +Character *Town::doTownOptions(Character *c) { + switch (_townActionId) { + case 0: + if (_buttonValue == Common::KEYCODE_d) + _buttonValue = 0; + else if (_buttonValue == Common::KEYCODE_w) + _buttonValue = 1; + else + break; + + depositWithdrawl(_buttonValue); + break; + + default: + // TODO: remaining cases + error("TODO: doTownOptions"); + } + + return c; +} + +void Town::depositWithdrawl(int choice) { + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + int gold, gems; + + if (choice) { + gold = party._bankGold; + gems = party._bankGems; + } else { + gold = party._gold; + gems = party._gems; + } + + for (uint idx = 0; idx < _buttons.size(); ++idx) + _buttons[idx]._sprites = &_icons1; + _buttons[0]._value = Common::KEYCODE_o; + _buttons[1]._value = Common::KEYCODE_e; + _buttons[2]._value = Common::KEYCODE_ESCAPE; + + Common::String msg = Common::String::format(GOLD_GEMS, + DEPOSIT_WITHDRAWL[choice], + XeenEngine::printMil(gold).c_str(), + XeenEngine::printMil(gems).c_str()); + + screen._windows[35].open(); + screen._windows[35].writeString(msg); + drawButtons(&screen._windows[35]); + screen._windows[35].update(); + + sound.playSample(nullptr, 0); + File f("coina.voc"); + bool flag; + + do { + bool flag; + switch (townWait()) { + case Common::KEYCODE_o: + continue; + case Common::KEYCODE_e: + flag = 1; + break; + default: + flag = 0; + break; + } + + if ((choice && !party._bankGems && flag) || + (choice && !party._bankGold && !flag) || + (choice && !party._gems && flag) || + (choice && !party._gold && !flag)) { + notEnough(flag, choice, 1, WT_2); + } else { + screen._windows[35].writeString(AMOUNT); + + // TODO + } + // TODO + } while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE); + +} + +void Town::notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait) { + SoundManager &sound = *_vm->_sound; - error("TODO: doTownOptions"); + Common::String msg = Common::String::format( + mode ? NO_X_IN_THE_Y : NOT_ENOUGH_X_IN_THE_Y, + CONSUMABLE_NAMES[consumableId], WHERE_NAMES[whereId]); + ErrorScroll::show(_vm, msg, wait); } diff --git a/engines/xeen/town.h b/engines/xeen/town.h index 07e9badc46..068cc8252b 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/str-array.h" #include "xeen/dialogs.h" +#include "xeen/dialogs_error.h" #include "xeen/party.h" namespace Xeen { @@ -71,9 +72,13 @@ private: Common::String createTownText(Character &ch); - void townWait(); + int townWait(); - Character *doTownOptions(Character *charP); + Character *doTownOptions(Character *c); + + void depositWithdrawl(int choice); + + void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait); public: Town(XeenEngine *vm); -- cgit v1.2.3 From 5030d0046f9f36965c5479d0fd0006461d32e5f4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 27 Jan 2015 08:51:08 -0500 Subject: XEEN: Implemented depositWithdrawl and subtract --- engines/xeen/party.h | 10 ++-- engines/xeen/resources.cpp | 7 +++ engines/xeen/resources.h | 2 + engines/xeen/town.cpp | 124 ++++++++++++++++++++++++++++++++++++++++----- engines/xeen/town.h | 2 + 5 files changed, 126 insertions(+), 19 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 0b7572cccf..883b378e55 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -218,7 +218,7 @@ public: int _day; int _year; int _minutes; - int _food; + uint _food; int _lightCount; int _torchCount; int _fireResistence; @@ -228,10 +228,10 @@ public: int _deathCount; int _winCount; int _lossCount; - int _gold; - int _gems; - int _bankGold; - int _bankGems; + uint _gold; + uint _gems; + uint _bankGold; + uint _bankGems; int _totalTime; bool _rested; bool _gameFlags[512]; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index cab6e2643d..3be2617e6b 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -657,6 +657,13 @@ const char *const GOLD_GEMS = "\x0C""37o\x0C""dld\x09""040G\x0C\x03""7e" "\x0C""dms\x09""067ESC\x01"; +const char *const GOLD_GEMS_2 = + "\x09""000\x0B""000\x03""c%s\x03l\n" + "\n" + "\x04""077Gold\x03r\x09""000%s\x03l\n" + "\x04""077Gems\x03r\x09""000%s\x03l\x09""000\x0B""051\x04""077\n" + "\x04""077"; + const char *const DEPOSIT_WITHDRAWL[2] = { "Deposit", "Withdrawl" }; const char *const NOT_ENOUGH_X_IN_THE_Y = diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 7461888c05..5dbc32174a 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -184,6 +184,8 @@ extern const char *const TRAINING_TEXT; extern const char *const GOLD_GEMS; +extern const char *const GOLD_GEMS_2; + extern const char *const DEPOSIT_WITHDRAWL[2]; extern const char *const NOT_ENOUGH_X_IN_THE_Y; diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index dceb79c354..9e1f04785f 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -21,6 +21,7 @@ */ #include "xeen/town.h" +#include "xeen/dialogs_input.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -322,7 +323,6 @@ void Town::dwarfEvent() { } Common::String Town::createTownText(Character &ch) { - Interface &intf = *_vm->_interface; Party &party = *_vm->_party; Common::String msg; @@ -507,7 +507,7 @@ void Town::depositWithdrawl(int choice) { } for (uint idx = 0; idx < _buttons.size(); ++idx) - _buttons[idx]._sprites = &_icons1; + _buttons[idx]._sprites = &_icons2; _buttons[0]._value = Common::KEYCODE_o; _buttons[1]._value = Common::KEYCODE_e; _buttons[2]._value = Common::KEYCODE_ESCAPE; @@ -523,45 +523,141 @@ void Town::depositWithdrawl(int choice) { screen._windows[35].update(); sound.playSample(nullptr, 0); - File f("coina.voc"); - bool flag; + File voc("coina.voc"); + bool flag = false; do { - bool flag; switch (townWait()) { case Common::KEYCODE_o: - continue; + flag = false; + break; case Common::KEYCODE_e: - flag = 1; + flag = true; break; - default: - flag = 0; + case Common::KEYCODE_ESCAPE: break; + default: + continue; } if ((choice && !party._bankGems && flag) || (choice && !party._bankGold && !flag) || - (choice && !party._gems && flag) || - (choice && !party._gold && !flag)) { + (!choice && !party._gems && flag) || + (!choice && !party._gold && !flag)) { notEnough(flag, choice, 1, WT_2); } else { screen._windows[35].writeString(AMOUNT); + int amount = NumericInput::show(_vm, 35, 10, 77); + + if (amount) { + if (flag) { + if (subtract(true, amount, choice, WT_2)) { + if (choice) { + party._gems += amount; + } else { + party._bankGems += amount; + } + } + } else { + if (subtract(false, amount, choice, WT_2)) { + if (choice) { + party._gold += amount; + } else { + party._bankGold += amount; + } + } + } + } - // TODO + uint gold, gems; + if (choice) { + gold = party._bankGold; + gems = party._bankGems; + } else { + gold = party._gold; + gems = party._gems; + } + + sound.playSample(&voc, 0); + msg = Common::String::format(GOLD_GEMS_2, DEPOSIT_WITHDRAWL[choice], + XeenEngine::printMil(gold), XeenEngine::printMil(gems)); + screen._windows[35].writeString(msg); + screen._windows[35].update(); } // TODO } while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE); + for (uint idx = 0; idx < _buttons.size(); ++idx) + _buttons[idx]._sprites = &_icons1; + _buttons[0]._value = Common::KEYCODE_d; + _buttons[1]._value = Common::KEYCODE_w; + _buttons[2]._value = Common::KEYCODE_ESCAPE; } void Town::notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait) { - SoundManager &sound = *_vm->_sound; - Common::String msg = Common::String::format( mode ? NO_X_IN_THE_Y : NOT_ENOUGH_X_IN_THE_Y, CONSUMABLE_NAMES[consumableId], WHERE_NAMES[whereId]); ErrorScroll::show(_vm, msg, wait); } +int Town::subtract(int mode, uint amount, int whereId, ErrorWaitType wait) { + Party &party = *_vm->_party; + + switch (mode) { + case 0: + // Gold + if (whereId) { + if (amount <= party._bankGold) { + party._bankGold -= amount; + } else { + notEnough(0, whereId, false, wait); + return false; + } + } else { + if (amount <= party._gold) { + party._gold -= amount; + } else { + notEnough(0, whereId, false, wait); + return false; + } + } + break; + + case 1: + // Gems + if (whereId) { + if (amount <= party._bankGems) { + party._bankGems -= amount; + } else { + notEnough(0, whereId, false, wait); + return false; + } + } else { + if (amount <= party._gems) { + party._gems -= amount; + } else { + notEnough(0, whereId, false, wait); + return false; + } + } + break; + + case 2: + // Food + if (amount > party._food) { + party._food -= amount; + } else { + notEnough(5, 0, 0, wait); + return false; + } + break; + + default: + break; + } + + return true; +} } // End of namespace Xeen diff --git a/engines/xeen/town.h b/engines/xeen/town.h index 068cc8252b..df754d5cef 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -79,6 +79,8 @@ private: void depositWithdrawl(int choice); void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait); + + int subtract(int mode, uint amount, int whereId, ErrorWaitType wait); public: Town(XeenEngine *vm); -- cgit v1.2.3 From 689776d922ca719e5a6749c0e3ec0b6d1884852d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 27 Jan 2015 22:04:23 -0500 Subject: XEEN: Implemented doTownOptions --- engines/xeen/dialogs_yesno.cpp | 2 +- engines/xeen/dialogs_yesno.h | 2 +- engines/xeen/interface_map.cpp | 8 +- engines/xeen/items.h | 2 + engines/xeen/party.cpp | 30 +-- engines/xeen/party.h | 10 +- engines/xeen/resources.cpp | 30 +++ engines/xeen/resources.h | 10 + engines/xeen/scripts.cpp | 2 +- engines/xeen/sound.h | 2 +- engines/xeen/town.cpp | 478 ++++++++++++++++++++++++++++++++++++++++- engines/xeen/town.h | 21 ++ 12 files changed, 562 insertions(+), 35 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp index 940f5b6e08..07de5a582f 100644 --- a/engines/xeen/dialogs_yesno.cpp +++ b/engines/xeen/dialogs_yesno.cpp @@ -25,7 +25,7 @@ namespace Xeen { -bool YesNo::show(XeenEngine *vm, bool type, int v2) { +bool YesNo::show(XeenEngine *vm, bool type, bool v2) { YesNo *dlg = new YesNo(vm); bool result = dlg->execute(type, v2); delete dlg; diff --git a/engines/xeen/dialogs_yesno.h b/engines/xeen/dialogs_yesno.h index 82ac402c85..d083cd64d4 100644 --- a/engines/xeen/dialogs_yesno.h +++ b/engines/xeen/dialogs_yesno.h @@ -35,7 +35,7 @@ private: bool execute(bool type, int v2); public: - static bool show(XeenEngine *vm, bool type, int v2); + static bool show(XeenEngine *vm, bool type, bool v2); }; } // End of namespace Xeen diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index c9ea2589c6..f90d3e369a 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -4552,26 +4552,26 @@ void InterfaceMap::assembleBorder() { // Draw UI element for blessed _blessSprites.draw(screen, 16, Common::Point(33, 137)); - if (_vm->_party->_blessedActive) { + if (_vm->_party->_blessed) { _blessedUIFrame = (_blessedUIFrame + 1) % 4; _blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137)); } // Draw UI element for power shield - if (_vm->_party->_powerShieldActive) { + if (_vm->_party->_powerShield) { _powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4; _blessSprites.draw(screen, _powerShieldUIFrame + 4, Common::Point(55, 137)); } // Draw UI element for holy bonus - if (_vm->_party->_holyBonusActive) { + if (_vm->_party->_holyBonus) { _holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4; _blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137)); } // Draw UI element for heroism - if (_vm->_party->_heroismActive) { + if (_vm->_party->_heroism) { _heroismUIFrame = (_heroismUIFrame + 1) % 4; _blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137)); } diff --git a/engines/xeen/items.h b/engines/xeen/items.h index 95a5519400..958a0b8afc 100644 --- a/engines/xeen/items.h +++ b/engines/xeen/items.h @@ -30,6 +30,8 @@ namespace Xeen { #define TOTAL_ITEMS 10 +enum BonusFlags { FLAG_CURSED = 0x40 }; + class XeenItem { public: int _material; diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 1baa25404f..66ba405909 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -60,7 +60,7 @@ Character::Character() { _lloydSide = 0; Common::fill(&_conditions[0], &_conditions[16], 0); _townUnknown = 0; - _unknown2 = 0; + _savedMazeId = 0; _currentHp = 0; _currentSp = 0; _ybDay = 0; @@ -140,7 +140,7 @@ void Character::synchronize(Common::Serializer &s) { s.syncAsByte(_conditions[i]); s.syncAsUint16LE(_townUnknown); - s.syncAsByte(_unknown2); + s.syncAsByte(_savedMazeId); s.syncAsUint16LE(_currentHp); s.syncAsUint16LE(_currentSp); s.syncAsUint16LE(_ybDay); @@ -381,7 +381,7 @@ int Character::getArmorClass(bool baseOnly) const { int result = statBonus(getStat(SPEED)) + itemScan(9); if (!baseOnly) - result += (party._blessedActive ? 1 : 0) + _ACTemp; + result += party._blessed + _ACTemp; return MAX(result, 0); } @@ -842,10 +842,10 @@ Party::Party(XeenEngine *vm) { _wizardEyeActive = false; _clairvoyanceActive = false; _walkOnWaterActive = false; - _blessedActive = false; - _powerShieldActive = false; - _holyBonusActive = false; - _heroismActive = false; + _blessed = 0; + _powerShield = 0; + _holyBonus = 0; + _heroism = 0; _difficulty = ADVENTURER; _cloudsEnd = false; _darkSideEnd = false; @@ -912,10 +912,10 @@ void Party::synchronize(Common::Serializer &s) { s.syncAsByte(_wizardEyeActive); s.syncAsByte(_clairvoyanceActive); s.syncAsByte(_walkOnWaterActive); - s.syncAsByte(_blessedActive); - s.syncAsByte(_powerShieldActive); - s.syncAsByte(_holyBonusActive); - s.syncAsByte(_heroismActive); + s.syncAsByte(_blessed); + s.syncAsByte(_powerShield); + s.syncAsByte(_holyBonus); + s.syncAsByte(_heroism); s.syncAsByte(_difficulty); for (int i = 0; i < ITEMS_COUNT; ++i) @@ -1194,10 +1194,10 @@ void Party::resetTemps() { _walkOnWaterActive = false; _wizardEyeActive = false; _clairvoyanceActive = false; - _heroismActive = false; - _holyBonusActive = false; - _powerShieldActive = false; - _blessedActive = false; + _heroism = 0; + _holyBonus = 0; + _powerShield = 0; + _blessed = 0; } void Party::handleLight() { diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 883b378e55..10f4027dfe 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -127,7 +127,7 @@ public: AttributePair _magicResistence; int _conditions[16]; int _townUnknown; - int _unknown2; + int _savedMazeId; int _currentHp; int _currentSp; int _ybDay; @@ -202,10 +202,10 @@ public: bool _wizardEyeActive; bool _clairvoyanceActive; bool _walkOnWaterActive; - bool _blessedActive; - bool _powerShieldActive; - bool _holyBonusActive; - bool _heroismActive; + int _blessed; + int _powerShield; + int _holyBonus; + int _heroism; Difficulty _difficulty; XeenItem _blacksmithWeapons[ITEMS_COUNT]; XeenItem _blacksmithArmor[ITEMS_COUNT]; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 3be2617e6b..5eec5be89e 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -626,6 +626,34 @@ const char *const FOOD_AND_DRINK = "\x09""017\x0C""37T\x0C""dip\n" "\x09""017\x0C""37R\x0C""dumors"; +const char *const GOOD_STUFF = "\n" + "\n" + "Good Stuff\n" + "\n" + "Hit a key!"; + +const char *const HAVE_A_DRINK = "\n\nHave a Drink\n\nHit a key!"; + +const char *const YOURE_DRUNK = "\n\nYou're Drunk\n\nHit a key!"; + +const int TAVERN_EXIT_LIST[2][6][5][2] = { + { + { { 21, 17 }, { 0, 0 }, { 20, 3 }, { 0, 0 }, { 0, 0 } }, + { { 13, 4 }, { 0, 0 }, { 19, 9 }, { 0, 0 }, { 0, 0 } }, + { { 20, 10 }, { 12, 8 }, { 5, 26 }, { 3, 4 }, { 7, 5 } }, + { { 18, 4 }, { 0, 0 }, { 19, 16 }, { 0, 0 }, { 11, 12 } }, + { { 15, 21 }, { 0, 0 }, { 13, 21 }, { 0, 0 }, { 0, 0 } }, + { { 10, 8 }, { 0, 0 }, { 15, 12 }, { 0, 0 }, { 0, 0 } }, + }, { + { { 21, 17 }, { 0, 0 }, { 20, 3 }, { 0, 0 }, { 0, 0 } }, + { { 13, 4 }, { 0, 0 }, { 19, 9 }, { 0, 0 }, { 0, 0 } }, + { { 20, 10 }, { 12, 8 }, { 5, 26 }, { 3, 4 }, { 7, 5 } }, + { { 17, 24 }, { 14, 13 }, { 0, 0 }, { 0, 0 }, { 9, 4 } }, + { { 15, 21 }, { 0, 0 }, { 13, 21 }, { 0, 0 }, { 0, 0 } }, + { { 10, 8 }, { 0, 0 }, { 15, 12 }, { 0, 0 }, { 0, 0 } } + } +}; + const char *const TEMPLE_TEXT = "\x0D\x03""c\x0B""000\x09""000Temple Options for" "\x09""039\x0B""027%s\x03l\x09""000\x0B""046" @@ -683,4 +711,6 @@ const char *const WHERE_NAMES[2] = { "Party", "Bank" }; const char *const AMOUNT = "\x03""c\x09""000\x0B""051Amount\x03l\n"; +const char *const FOOD_PACKS_FULL = "\v007Your food packs are already full!"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 5dbc32174a..497b02515b 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -170,6 +170,14 @@ extern const char *const GUILD_TEXT; extern const char *const TAVERN_TEXT; +extern const char *const GOOD_STUFF; + +extern const char *const HAVE_A_DRINK; + +extern const char *const YOURE_DRUNK; + +extern const int TAVERN_EXIT_LIST[2][6][5][2]; + extern const char *const FOOD_AND_DRINK; extern const char *const TEMPLE_TEXT; @@ -200,6 +208,8 @@ extern const char *const WHERE_NAMES[2]; extern const char *const AMOUNT; +extern const char *const FOOD_PACKS_FULL; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index e3cc682069..c84ec91d11 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -1077,7 +1077,7 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { v = ps._luck._temporary; break; case 44: - v = YesNo::show(_vm, mask, 0); + v = YesNo::show(_vm, mask, false); v = (!v && !mask) ? 2 : mask; break; case 45: diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index d38e16b5b9..b6f1948726 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -43,7 +43,7 @@ public: void playSong(Common::SeekableReadStream &f) {} - void playSample(const Common::SeekableReadStream *stream, int v2) {} + void playSample(const Common::SeekableReadStream *stream, int v2 = 1) {} void playFX(int id) {} }; diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 9e1f04785f..81cc88bb2c 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -22,6 +22,7 @@ #include "xeen/town.h" #include "xeen/dialogs_input.h" +#include "xeen/dialogs_yesno.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -42,6 +43,11 @@ Town::Town(XeenEngine *vm) : _vm(vm) { _v12 = _v13 = 0; _v14 = 0; _v20 = 0; + _v21 = 0; + _v22 = 0; + _v23 = 0; + _v24 = 0; + _dayOfWeek = 0; _uncurseCost = 0; _flag1 = false; _nextExperienceLevel = 0; @@ -474,19 +480,469 @@ Common::String Town::createTownText(Character &ch) { Character *Town::doTownOptions(Character *c) { switch (_townActionId) { case 0: - if (_buttonValue == Common::KEYCODE_d) + // Bank + c = doBankOptions(c); + break; + case 1: + // Blacksmith + c = doBlacksmithOptions(c); + break; + case 2: + // Guild + c = doGuildOptions(c); + break; + case 3: + // Tavern + c = doTavernOptions(c); + break; + case 4: + // Temple + c = doTempleOptions(c); + case 5: + // Training + c = doTrainingOptions(c); + break; + default: + break; + } + + return c; +} + +Character *Town::doBankOptions(Character *c) { + if (_buttonValue == Common::KEYCODE_d) + _buttonValue = 0; + else if (_buttonValue == Common::KEYCODE_w) + _buttonValue = 1; + else + return c; + + depositWithdrawl(_buttonValue); + return c; +} + +Character *Town::doBlacksmithOptions(Character *c) { + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + + if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) { + // Switch character + _buttonValue -= Common::KEYCODE_F1; + if (_buttonValue < party._partyCount) { + c = &party._activeParty[_buttonValue]; + intf.highlightChar(_buttonValue); + } + } + else if (_buttonValue == Common::KEYCODE_c) { + c = showItems(c, 1); + _buttonValue = 0; + } + + return c; +} + +Character *Town::doGuildOptions(Character *c) { + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + bool isDarkCc = _vm->_files->_isDarkCc; + + if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) { + // Switch character + _buttonValue -= Common::KEYCODE_F1; + if (_buttonValue < party._partyCount) { + c = &party._activeParty[_buttonValue]; + intf.highlightChar(_buttonValue); + + if (!c->guildMember()) { + sound.playSample(nullptr, 0); + intf._overallFrame = 5; + File f(isDarkCc ? "skull1.voc" : "guild11.voc"); + sound.playSample(&f, 1); + } + } + } + else if (_buttonValue == Common::KEYCODE_s) { + if (c->guildMember()) + c = showAvailableSpells(c); + _buttonValue = 0; + } else if (_buttonValue == Common::KEYCODE_c) { + if (!c->noActions()) { + if (c->guildMember()) + c = showAvailableSpells(c); _buttonValue = 0; - else if (_buttonValue == Common::KEYCODE_w) - _buttonValue = 1; + } + } + + return c; +} + +Character *Town::doTavernOptions(Character *c) { + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + Screen &screen = *_vm->_screen; + bool isDarkCc = _vm->_files->_isDarkCc; + int idx = 0; + + switch (_buttonValue) { + case Common::KEYCODE_F1: + case Common::KEYCODE_F2: + case Common::KEYCODE_F3: + case Common::KEYCODE_F4: + case Common::KEYCODE_F5: + case Common::KEYCODE_F6: + // Switch character + _buttonValue -= Common::KEYCODE_F1; + if (_buttonValue < party._partyCount) { + c = &party._activeParty[_buttonValue]; + intf.highlightChar(_buttonValue); + _v21 = 0; + } + break; + case Common::KEYCODE_d: + // Drink + if (!c->noActions()) { + if (subtract(0, 1, 0, WT_2)) { + sound.playSample(nullptr, 0); + File f("gulp.voc"); + sound.playSample(&f, 0); + _v21 = 1; + + screen._windows[10].writeString(Common::String::format(TAVERN_TEXT, + c->_name.c_str(), GOOD_STUFF, + XeenEngine::printMil(party._gold))); + drawButtons(&screen._windows[0]); + screen._windows[10].update(); + + if (_vm->getRandomNumber(100) < 26) { + ++c->_conditions[DRUNK]; + intf.charIconsPrint(true); + sound.playFX(28); + } + + townWait(); + } + } + break; + case Common::KEYCODE_f: { + if (party._mazeId == (isDarkCc ? 29 : 28)) { + _v22 = party._partyCount * 15; + _v23 = 10; + idx = 0; + } else if (isDarkCc && party._mazeId == 31) { + _v22 = party._partyCount * 60; + _v23 = 100; + idx = 1; + } else if (!isDarkCc && party._mazeId == 30) { + _v22 = party._partyCount * 50; + _v23 = 50; + idx = 1; + } else if (isDarkCc) { + _v22 = party._partyCount * 120; + _v23 = 250; + idx = 2; + } else if (party._mazeId == 49) { + _v22 = party._partyCount * 120; + _v23 = 100; + idx = 2; + } else { + _v22 = party._partyCount * 15; + _v23 = 10; + idx = 0; + } + + Common::String msg = _textStrings[(isDarkCc ? 60 : 75) + idx]; + screen._windows[10].close(); + screen._windows[12].open(); + screen._windows[12].writeString(msg); + + if (YesNo::show(_vm, false, true)) { + if (party._food >= _v22) { + ErrorScroll::show(_vm, FOOD_PACKS_FULL, WT_2); + } else if (subtract(0, _v23, 0, WT_2)) { + party._food = _v22; + sound.playSample(nullptr, 0); + File f(isDarkCc ? "thanks2.voc" : "thankyou.voc"); + sound.playSample(&f, 1); + } + } + + screen._windows[12].close(); + screen._windows[10].open(); + _buttonValue = 0; + break; + } + + case Common::KEYCODE_r: { + if (party._mazeId == (isDarkCc ? 29 : 28)) { + idx = 0; + } else if (party._mazeId == (isDarkCc ? 31 : 30)) { + idx = 10; + } else if (isDarkCc || party._mazeId == 49) { + idx = 20; + } + + Common::String msg = Common::String::format("\x03""c\x0B""012%s", + _textStrings[(party._day % 10) + idx]); + Window &w = screen._windows[12]; + w.open(); + w.writeString(msg); + w.update(); + + townWait(); + w.close(); + break; + } + + case Common::KEYCODE_s: { + // Save game + // TODO: This needs to be fit in better with ScummVM framework + int idx = isDarkCc ? (party._mazeId - 29) >> 1 : party._mazeId - 28; + assert(idx >= 0); + party._mazePosition.x = TAVERN_EXIT_LIST[isDarkCc ? 1 : 0][_townActionId][idx][0]; + party._mazePosition.y = TAVERN_EXIT_LIST[isDarkCc ? 1 : 0][_townActionId][idx][1]; + + if (!isDarkCc || party._mazeId == 29) + party._mazeDirection = DIR_WEST; + else if (party._mazeId == 31) + party._mazeDirection = DIR_EAST; else - break; + party._mazeDirection = DIR_SOUTH; + + party._priorMazeId = party._mazeId; + for (int idx = 0; idx < party._partyCount; ++idx) { + party._activeParty[idx]._savedMazeId = party._mazeId; + party._activeParty[idx]._xeenSide = map._loadDarkSide; + } + + party.addTime(1440); + party._mazeId = 0; + _vm->quitGame(); + break; + } + + case Common::KEYCODE_t: + if (!c->noActions()) { + if (!_v21) { + screen._windows[10].writeString(Common::String::format(TAVERN_TEXT, + c->_name.c_str(), HAVE_A_DRINK, + XeenEngine::printMil(party._gold))); + drawButtons(&screen); + screen._windows[10].update(); + townWait(); + } else { + _v21 = 0; + if (c->_conditions[DRUNK]) { + screen._windows[10].writeString(Common::String::format(TAVERN_TEXT, + c->_name.c_str(), YOURE_DRUNK, + XeenEngine::printMil(party._gold))); + drawButtons(&screen); + screen._windows[10].update(); + townWait(); + } else if (subtract(0, 1, 0, WT_2)) { + sound.playSample(nullptr, 0); + File f(isDarkCc ? "thanks2.voc" : "thankyou.voc"); + sound.playSample(&f, 1); + + if (party._mazeId == (isDarkCc ? 29 : 28)) { + _v24 = 30; + } else if (isDarkCc && party._mazeId == 31) { + _v24 = 40; + } else if (!isDarkCc && party._mazeId == 45) { + _v24 = 45; + } else if (!isDarkCc && party._mazeId == 49) { + _v24 = 60; + } else if (isDarkCc) { + _v24 = 50; + } + + Common::String msg = _textStrings[map.mazeData()._tavernTips + _v24]; + map.mazeData()._tavernTips = (map.mazeData()._tavernTips + 1) / + (isDarkCc ? 10 : 15); - depositWithdrawl(_buttonValue); + Window &w = screen._windows[12]; + w.open(); + w.writeString(Common::String::format("\x03""c\x0B""012%s", msg.c_str())); + w.update(); + townWait(); + w.close(); + } + } + } break; default: - // TODO: remaining cases - error("TODO: doTownOptions"); + break; + } + + return c; +} + +Character *Town::doTempleOptions(Character *c) { + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + switch (_buttonValue) { + case Common::KEYCODE_F1: + case Common::KEYCODE_F2: + case Common::KEYCODE_F3: + case Common::KEYCODE_F4: + case Common::KEYCODE_F5: + case Common::KEYCODE_F6: + // Switch character + _buttonValue -= Common::KEYCODE_F1; + if (_buttonValue < party._partyCount) { + c = &party._activeParty[_buttonValue]; + intf.highlightChar(_buttonValue); + _dayOfWeek = 0; + } + break; + + case Common::KEYCODE_d: + if (_donation && subtract(0, _donation, 0, WT_2)) { + sound.playSample(nullptr, 0); + File f("coina.voc"); + sound.playSample(&f, 1); + _dayOfWeek = (_dayOfWeek + 1) / 10; + + if (_dayOfWeek == (party._day / 10)) { + party._clairvoyanceActive = true; + party._lightCount = 1; + + int amt = _dayOfWeek ? _dayOfWeek : 10; + party._heroism = amt; + party._holyBonus = amt; + party._powerShield = amt; + party._blessed = amt; + + intf.charIconsPrint(true); + sound.playSample(nullptr, 0); + File f("ahh.voc"); + sound.playSample(&f, 1); + _flag1 = true; + _donation = 0; + } + } + break; + + case Common::KEYCODE_h: + if (_healCost && subtract(0, _healCost, 0, WT_2)) { + c->_magicResistence._temporary = 0; + c->_energyResistence._temporary = 0; + c->_poisonResistence._temporary = 0; + c->_electricityResistence._temporary = 0; + c->_coldResistence._temporary = 0; + c->_fireResistence._temporary = 0; + c->_ACTemp = 0; + c->_level._temporary = 0; + c->_luck._temporary = 0; + c->_accuracy._temporary = 0; + c->_speed._temporary = 0; + c->_endurance._temporary = 0; + c->_personality._temporary = 0; + c->_intellect._temporary = 0; + c->_might._temporary = 0; + c->_currentHp = c->getMaxHP(); + Common::fill(&c->_conditions[HEART_BROKEN], &c->_conditions[NO_CONDITION], 0); + + _v1 = 1440; + intf.charIconsPrint(true); + sound.playSample(nullptr, 0); + File f("ahh.voc"); + sound.playSample(&f, 1); + } + break; + + case Common::KEYCODE_u: + if (_uncurseCost && subtract(0, _uncurseCost, 0, WT_2)) { + for (int idx = 0; idx < 9; ++idx) { + c->_weapons[idx]._bonusFlags &= ~FLAG_CURSED; + c->_armor[idx]._bonusFlags &= ~FLAG_CURSED; + c->_accessories[idx]._bonusFlags &= ~FLAG_CURSED; + c->_misc[idx]._bonusFlags &= ~FLAG_CURSED; + } + + _v1 = 1440; + intf.charIconsPrint(true); + sound.playSample(nullptr, 0); + File f("ahh.voc"); + sound.playSample(&f, 1); + } + break; + + default: + break; + } + + return c; +} + +Character *Town::doTrainingOptions(Character *c) { + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + bool isDarkCc = _vm->_files->_isDarkCc; + + switch (_buttonValue) { + case Common::KEYCODE_F1: + case Common::KEYCODE_F2: + case Common::KEYCODE_F3: + case Common::KEYCODE_F4: + case Common::KEYCODE_F5: + case Common::KEYCODE_F6: + // Switch character + _buttonValue -= Common::KEYCODE_F1; + if (_buttonValue < party._partyCount) { + _v2 = _buttonValue; + c = &party._activeParty[_buttonValue]; + intf.highlightChar(_buttonValue); + } + break; + + case Common::KEYCODE_t: + if (_nextExperienceLevel) { + sound.playSample(nullptr, 0); + _townCurrent = 0; + + Common::String name; + if (c->_level._permanent >= _v20) { + name = isDarkCc ? "gtlost.voc" : "trainin1.voc"; + } else { + name = isDarkCc ? "gtlost.voc" : "trainin0.voc"; + } + + File f(name); + sound.playSample(&f); + + } else if (!c->noActions()) { + if (subtract(0, (c->_level._permanent * c->_level._permanent) * 10, 0, WT_2)) { + _townCurrent = 0; + sound.playSample(nullptr, 0); + File f(isDarkCc ? "prtygd.voc" : "trainin2.voc"); + sound.playSample(&f, 1); + + c->_experience -= c->currentExperienceLevel() - + (c->getCurrentExperience() - c->_experience); + c->_level._permanent++; + + if (!_arr1[_v2]) { + party.addTime(1440); + _arr1[_v2] = 1; + } + + party.resetTemps(); + c->_currentHp = c->getMaxHP(); + c->_currentSp = c->getMaxSP(); + intf.charIconsPrint(true); + } + } + break; + + default: + break; } return c; @@ -660,4 +1116,12 @@ int Town::subtract(int mode, uint amount, int whereId, ErrorWaitType wait) { return true; } +Character *Town::showItems(Character *c, int v2) { + error("TODO: showItems"); +} + +Character *Town::showAvailableSpells(Character *c) { + error("TODO: showAvailableSpells"); +} + } // End of namespace Xeen diff --git a/engines/xeen/town.h b/engines/xeen/town.h index df754d5cef..950d702d4a 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -49,6 +49,11 @@ private: int _v10, _v11, _v12; int _v13, _v14; int _v20; + int _v21; + uint _v22; + int _v23; + int _v24; + int _dayOfWeek; int _uncurseCost; Common::Point _townPos; int _arr1[6]; @@ -76,11 +81,27 @@ private: Character *doTownOptions(Character *c); + Character *doBankOptions(Character *c); + + Character *doBlacksmithOptions(Character *c); + + Character *doGuildOptions(Character *c); + + Character *doTavernOptions(Character *c); + + Character *doTempleOptions(Character *c); + + Character *doTrainingOptions(Character *c); + void depositWithdrawl(int choice); void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait); int subtract(int mode, uint amount, int whereId, ErrorWaitType wait); + + Character *showItems(Character *c, int v2); + + Character *showAvailableSpells(Character *c); public: Town(XeenEngine *vm); -- cgit v1.2.3 From a755ce6e9215006bbafbcb28f46c30a03b464a4d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 27 Jan 2015 22:57:46 -0500 Subject: XEEN: Implement hilight/unhilightChar, bufixes for Tavern display --- engines/xeen/interface.cpp | 24 ++++++++++++++++++++++-- engines/xeen/interface.h | 1 + engines/xeen/town.cpp | 20 +++++++++++--------- engines/xeen/town.h | 2 +- 4 files changed, 35 insertions(+), 12 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 0126cd6d17..ece8ff3054 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -781,11 +781,31 @@ void Interface::doFalling() { } void Interface::highlightChar(int charId) { - error("TODO: highlightChar"); + Screen &screen = *_vm->_screen; + + if (charId != _hiliteChar && _hiliteChar != HILIGHT_CHAR_DISABLED) { + // Handle deselecting any previusly selected char + if (_hiliteChar != -1) { + _globalSprites.draw(screen, 9 + _hiliteChar, + Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149)); + } + + // Highlight new character + _globalSprites.draw(screen, 8, Common::Point(CHAR_FACES_X[charId] - 1, 149)); + _hiliteChar = charId; + screen._windows[33].update(); + } } void Interface::unhighlightChar() { - error("TODO: unhighlight"); + Screen &screen = *_vm->_screen; + + if (_hiliteChar != -1) { + _globalSprites.draw(screen, _hiliteChar + 9, + Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149)); + _hiliteChar = -1; + screen._windows[33].update(); + } } bool Interface::checkMoveDirection(int key) { diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index ab30654065..1630e80f69 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -34,6 +34,7 @@ namespace Xeen { class XeenEngine; #define MINIMAP_SIZE 7 +#define HILIGHT_CHAR_DISABLED -2 class Interface: public ButtonContainer, public InterfaceMap { private: diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 81cc88bb2c..af93d0016c 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -292,9 +292,11 @@ int Town::townWait() { EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; + _buttonValue = 0; while (!_vm->shouldQuit() && !_buttonValue) { events.updateGameCounter(); while (!_vm->shouldQuit() && !_buttonValue && events.timeElapsed() < 3) { + events.pollEventsAndWait(); checkEvents(_vm); } if (!_buttonValue) @@ -343,7 +345,7 @@ Common::String Town::createTownText(Character &ch) { case 1: // Blacksmith return Common::String::format(BLACKSMITH_TEXT, - XeenEngine::printMil(party._gold)); + XeenEngine::printMil(party._gold).c_str()); case 2: // Guild @@ -352,7 +354,7 @@ Common::String Town::createTownText(Character &ch) { case 3: // Tavern - return Common::String::format(TAVERN_TEXT, ch._name, + return Common::String::format(TAVERN_TEXT, ch._name.c_str(), FOOD_AND_DRINK, XeenEngine::printMil(party._gold).c_str()); case 4: @@ -564,12 +566,12 @@ Character *Town::doGuildOptions(Character *c) { } else if (_buttonValue == Common::KEYCODE_s) { if (c->guildMember()) - c = showAvailableSpells(c); + c = showAvailableSpells(c, 0x80); _buttonValue = 0; } else if (_buttonValue == Common::KEYCODE_c) { if (!c->noActions()) { if (c->guildMember()) - c = showAvailableSpells(c); + c = showAvailableSpells(c, 0); _buttonValue = 0; } } @@ -612,7 +614,7 @@ Character *Town::doTavernOptions(Character *c) { screen._windows[10].writeString(Common::String::format(TAVERN_TEXT, c->_name.c_str(), GOOD_STUFF, - XeenEngine::printMil(party._gold))); + XeenEngine::printMil(party._gold).c_str())); drawButtons(&screen._windows[0]); screen._windows[10].update(); @@ -728,7 +730,7 @@ Character *Town::doTavernOptions(Character *c) { if (!_v21) { screen._windows[10].writeString(Common::String::format(TAVERN_TEXT, c->_name.c_str(), HAVE_A_DRINK, - XeenEngine::printMil(party._gold))); + XeenEngine::printMil(party._gold).c_str())); drawButtons(&screen); screen._windows[10].update(); townWait(); @@ -737,7 +739,7 @@ Character *Town::doTavernOptions(Character *c) { if (c->_conditions[DRUNK]) { screen._windows[10].writeString(Common::String::format(TAVERN_TEXT, c->_name.c_str(), YOURE_DRUNK, - XeenEngine::printMil(party._gold))); + XeenEngine::printMil(party._gold).c_str())); drawButtons(&screen); screen._windows[10].update(); townWait(); @@ -1036,7 +1038,7 @@ void Town::depositWithdrawl(int choice) { sound.playSample(&voc, 0); msg = Common::String::format(GOLD_GEMS_2, DEPOSIT_WITHDRAWL[choice], - XeenEngine::printMil(gold), XeenEngine::printMil(gems)); + XeenEngine::printMil(gold).c_str(), XeenEngine::printMil(gems).c_str()); screen._windows[35].writeString(msg); screen._windows[35].update(); } @@ -1120,7 +1122,7 @@ Character *Town::showItems(Character *c, int v2) { error("TODO: showItems"); } -Character *Town::showAvailableSpells(Character *c) { +Character *Town::showAvailableSpells(Character *c, int v2) { error("TODO: showAvailableSpells"); } diff --git a/engines/xeen/town.h b/engines/xeen/town.h index 950d702d4a..88031cab8e 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -101,7 +101,7 @@ private: Character *showItems(Character *c, int v2); - Character *showAvailableSpells(Character *c); + Character *showAvailableSpells(Character *c, int v2); public: Town(XeenEngine *vm); -- cgit v1.2.3 From 8a324eb755cfa07cccfe2c1513522801863643c8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 28 Jan 2015 08:46:34 -0500 Subject: XEEN: Implemented drawTownAnim --- engines/xeen/dialogs_whowill.cpp | 3 +- engines/xeen/dialogs_yesno.cpp | 3 +- engines/xeen/interface_map.cpp | 4 -- engines/xeen/interface_map.h | 2 - engines/xeen/sound.h | 2 + engines/xeen/town.cpp | 136 ++++++++++++++++++++++++++++++++++++++- engines/xeen/town.h | 3 + 7 files changed, 142 insertions(+), 11 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_whowill.cpp b/engines/xeen/dialogs_whowill.cpp index 042214a3dc..fb845a6d9a 100644 --- a/engines/xeen/dialogs_whowill.cpp +++ b/engines/xeen/dialogs_whowill.cpp @@ -41,6 +41,7 @@ int WhoWill::execute(int message, int action, bool type) { Party &party = *_vm->_party; Screen &screen = *_vm->_screen; Scripts &scripts = *_vm->_scripts; + Town &town = *_vm->_town; int numFrames; if (party._partyCount <= 1) @@ -65,7 +66,7 @@ int WhoWill::execute(int message, int action, bool type) { events.updateGameCounter(); if (screen._windows[11]._enabled) { - intf.drawTownAnim(0); + town.drawTownAnim(0); screen._windows[36].frame(); numFrames = 3; } else { diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp index 07de5a582f..1c0c3a7fe2 100644 --- a/engines/xeen/dialogs_yesno.cpp +++ b/engines/xeen/dialogs_yesno.cpp @@ -39,6 +39,7 @@ bool YesNo::execute(bool type, int v2) { Interface &intf = *_vm->_interface; Map &map = *_vm->_map; Party &party = *_vm->_party; + Town &town = *_vm->_town; SpriteResource confirmSprites; int numFrames; bool result = false; @@ -67,7 +68,7 @@ bool YesNo::execute(bool type, int v2) { intf.draw3d(true); numFrames = 1; } else { - intf.drawTownAnim(v2); + town.drawTownAnim(v2); numFrames = 3; } diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index f90d3e369a..77a5f928c7 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -4964,8 +4964,4 @@ void InterfaceMap::drawMiniMap() { party._wizardEyeActive = eyeActive; } -void InterfaceMap::drawTownAnim(bool v) { - warning("TODO"); -} - } // End of namespace Xeen diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 153abba223..fb448e1f29 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -165,8 +165,6 @@ public: void drawOutdoors(); - void drawTownAnim(bool v); - void assembleBorder(); }; diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index b6f1948726..7e7df9caea 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -45,6 +45,8 @@ public: void playSample(const Common::SeekableReadStream *stream, int v2 = 1) {} + bool playSample(int v1, int v2) { return false; } + void playFX(int id) {} }; diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index af93d0016c..328301a73b 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -51,6 +51,7 @@ Town::Town(XeenEngine *vm) : _vm(vm) { _uncurseCost = 0; _flag1 = false; _nextExperienceLevel = 0; + _drawCtr1 = _drawCtr2 = 0; } void Town::loadStrings(const Common::String &name) { @@ -231,7 +232,7 @@ int Town::townAction(int actionId) { screen._windows[0].update(); intf.highlightChar(0); - intf.drawTownAnim(1); + drawTownAnim(1); if (actionId == 0) intf._overallFrame = 2; @@ -290,7 +291,6 @@ int Town::townAction(int actionId) { int Town::townWait() { EventsManager &events = *_vm->_events; - Interface &intf = *_vm->_interface; _buttonValue = 0; while (!_vm->shouldQuit() && !_buttonValue) { @@ -300,7 +300,7 @@ int Town::townWait() { checkEvents(_vm); } if (!_buttonValue) - intf.drawTownAnim(!_vm->_screen->_windows[11]._enabled); + drawTownAnim(!_vm->_screen->_windows[11]._enabled); } return _buttonValue; @@ -1118,6 +1118,136 @@ int Town::subtract(int mode, uint amount, int whereId, ErrorWaitType wait) { return true; } +void Town::drawTownAnim(bool flag) { + Interface &intf = *_vm->_interface; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + bool isDarkCc = _vm->_files->_isDarkCc; + + if (_townActionId == 1) { + if (sound.playSample(1, 0)) { + if (isDarkCc) { + _townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos); + _townSprites[2].draw(screen, _vm->getRandomNumber(11) == 1 ? 9 : 10, + Common::Point(34, 33)); + _townSprites[2].draw(screen, _vm->getRandomNumber(5) + 3, + Common::Point(34, 54)); + } + } else { + _townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos); + if (isDarkCc) { + _townSprites[2].draw(screen, _vm->getRandomNumber(11) == 1 ? 9 : 10, + Common::Point(34, 33)); + } + } + } else { + if (!isDarkCc || _townActionId != 5) { + if (!_townSprites[_townCurrent / 8].empty()) + _townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos); + } + } + + switch (_townActionId) { + case 0: + if (sound.playSample(1, 0) || (isDarkCc && intf._overallFrame)) { + if (isDarkCc) { + if (sound.playSample(1, 0) || intf._overallFrame == 1) { + _townSprites[4].draw(screen, _vm->getRandomNumber(13, 18), + Common::Point(8, 30)); + } else if (intf._overallFrame > 1) { + _townSprites[4].draw(screen, 13 - intf._overallFrame++, + Common::Point(8, 30)); + if (intf._overallFrame > 14) + intf._overallFrame = 0; + } + } else { + _townSprites[2].draw(screen, _vm->getRandomNumber(7, 11), Common::Point(8, 8)); + } + } + break; + + case 2: + if (sound.playSample(1, 0)) { + if (isDarkCc) { + if (intf._overallFrame) { + intf._overallFrame ^= 1; + _townSprites[6].draw(screen, intf._overallFrame, Common::Point(8, 106)); + } else { + _townSprites[6].draw(screen, _vm->getRandomNumber(3), Common::Point(16, 48)); + } + } + } + break; + + case 3: + if (sound.playSample(1, 0) && isDarkCc) { + _townSprites[4].draw(screen, _vm->getRandomNumber(7), Common::Point(153, 49)); + } + break; + case 4: + if (sound.playSample(1, 0)) { + _townSprites[3].draw(screen, _vm->getRandomNumber(2, 4), Common::Point(8, 8)); + + } + break; + + case 5: + if (sound.playSample(1, 0)) { + if (isDarkCc) { + _townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos); + } + } else { + if (isDarkCc) { + _townSprites[0].draw(screen, ++intf._overallFrame % 8, Common::Point(8, 8)); + _townSprites[5].draw(screen, _vm->getRandomNumber(5), Common::Point(61, 74)); + } else { + _townSprites[1].draw(screen, _vm->getRandomNumber(8, 12), Common::Point(8, 8)); + } + } + } + + if (flag) { + intf._face1UIFrame = 0; + intf._face2UIFrame = 0; + intf._dangerSenseUIFrame = 0; + intf._spotDoorsUIFrame = 0; + intf._batUIFrame = 0; + + intf.assembleBorder(); + } + + if (screen._windows[11]._enabled) { + _drawCtr1 = (_drawCtr1 + 1) % 2; + if (!_drawCtr1 || !_drawCtr2) { + _townCurrent = 0; + _drawCtr2 = 0; + } else { + _townCurrent = _vm->getRandomNumber(3); + } + } else { + _townCurrent = (_townCurrent + 1) % _townMaxId; + } + + if (isDarkCc) { + if (_townActionId == 1 && (_townCurrent == 4 || _townCurrent == 13)) + sound.playFX(45); + + if (_townActionId == 5 && _townCurrent == 23) { + File f("spit1.voc"); + sound.playSample(&f, 0); + } + } else { + if (_townMaxId == 32 || _townCurrent == 0) + _townCurrent = 17; + if (_townMaxId == 26 || _townCurrent == 0) + _townCurrent = 20; + if (_townActionId == 1 && (_townCurrent == 3 || _townCurrent == 9)) + sound.playFX(45); + } + + screen._windows[3].update(); +} + Character *Town::showItems(Character *c, int v2) { error("TODO: showItems"); } diff --git a/engines/xeen/town.h b/engines/xeen/town.h index 88031cab8e..e28d03cf5c 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -60,6 +60,7 @@ private: int _currentCharLevel; bool _flag1; uint _nextExperienceLevel; + int _drawCtr1, _drawCtr2; void loadStrings(const Common::String &name); @@ -106,6 +107,8 @@ public: Town(XeenEngine *vm); int townAction(int actionId); + + void drawTownAnim(bool flag); }; } // End of namespace Xeen -- cgit v1.2.3 From 5228879a1dfa2684ee71fe0577eb98dbbc92d55a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 28 Jan 2015 19:22:54 -0500 Subject: XEEN: Fix for entering/exiting tavern display --- engines/xeen/scripts.cpp | 4 +++- engines/xeen/town.cpp | 40 ++++++++++++++++++++-------------------- engines/xeen/town.h | 2 +- 3 files changed, 24 insertions(+), 22 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index c84ec91d11..11f88044f5 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -158,6 +158,7 @@ bool Scripts::checkEvents() { (_currentPos.x | _currentPos.y) && event._line == _lineNum) { if (event._direction == party._mazeDirection || event._direction == DIR_ALL) { _vm->_mode = MODE_9; + _scriptExecuted = true; doOpcode(event); break; } else { @@ -517,7 +518,8 @@ void Scripts::cmdSpawn(Common::Array<byte> ¶ms) { void Scripts::cmdDoTownEvent(Common::Array<byte> ¶ms) { _scriptResult = _vm->_town->townAction(params[0]); _vm->_party->_stepped = true; - + _refreshIcons = true; + cmdExit(params); } diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 328301a73b..a1b09712c5 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -32,7 +32,7 @@ Town::Town(XeenEngine *vm) : _vm(vm) { Common::fill(&_arr1[0], &_arr1[6], 0); _townMaxId = 0; _townActionId = 0; - _townCurrent = 0; + _drawFrameIndex = 0; _currentCharLevel = 0; _v1 = 0; _v2 = 0; @@ -77,7 +77,7 @@ int Town::townAction(int actionId) { _townMaxId = TOWN_MAXES[_vm->_files->_isDarkCc][actionId]; _townActionId = actionId; - _townCurrent = 0; + _drawFrameIndex = 0; _v1 = 0; _townPos = Common::Point(8, 8); intf._overallFrame = 0; @@ -217,7 +217,7 @@ int Town::townAction(int actionId) { intf._spotDoorsUIFrame = 0; intf._batUIFrame = 0; - _townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos); + _townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos); if (actionId == 0 && isDarkCc) { _townSprites[4].draw(screen, _vm->getRandomNumber(13, 18), Common::Point(8, 30)); @@ -907,7 +907,7 @@ Character *Town::doTrainingOptions(Character *c) { case Common::KEYCODE_t: if (_nextExperienceLevel) { sound.playSample(nullptr, 0); - _townCurrent = 0; + _drawFrameIndex = 0; Common::String name; if (c->_level._permanent >= _v20) { @@ -921,7 +921,7 @@ Character *Town::doTrainingOptions(Character *c) { } else if (!c->noActions()) { if (subtract(0, (c->_level._permanent * c->_level._permanent) * 10, 0, WT_2)) { - _townCurrent = 0; + _drawFrameIndex = 0; sound.playSample(nullptr, 0); File f(isDarkCc ? "prtygd.voc" : "trainin2.voc"); sound.playSample(&f, 1); @@ -1127,14 +1127,14 @@ void Town::drawTownAnim(bool flag) { if (_townActionId == 1) { if (sound.playSample(1, 0)) { if (isDarkCc) { - _townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos); + _townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos); _townSprites[2].draw(screen, _vm->getRandomNumber(11) == 1 ? 9 : 10, Common::Point(34, 33)); _townSprites[2].draw(screen, _vm->getRandomNumber(5) + 3, Common::Point(34, 54)); } } else { - _townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos); + _townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos); if (isDarkCc) { _townSprites[2].draw(screen, _vm->getRandomNumber(11) == 1 ? 9 : 10, Common::Point(34, 33)); @@ -1142,8 +1142,8 @@ void Town::drawTownAnim(bool flag) { } } else { if (!isDarkCc || _townActionId != 5) { - if (!_townSprites[_townCurrent / 8].empty()) - _townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos); + if (!_townSprites[_drawFrameIndex / 8].empty()) + _townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos); } } @@ -1194,7 +1194,7 @@ void Town::drawTownAnim(bool flag) { case 5: if (sound.playSample(1, 0)) { if (isDarkCc) { - _townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos); + _townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos); } } else { if (isDarkCc) { @@ -1219,29 +1219,29 @@ void Town::drawTownAnim(bool flag) { if (screen._windows[11]._enabled) { _drawCtr1 = (_drawCtr1 + 1) % 2; if (!_drawCtr1 || !_drawCtr2) { - _townCurrent = 0; + _drawFrameIndex = 0; _drawCtr2 = 0; } else { - _townCurrent = _vm->getRandomNumber(3); + _drawFrameIndex = _vm->getRandomNumber(3); } } else { - _townCurrent = (_townCurrent + 1) % _townMaxId; + _drawFrameIndex = (_drawFrameIndex + 1) % _townMaxId; } if (isDarkCc) { - if (_townActionId == 1 && (_townCurrent == 4 || _townCurrent == 13)) + if (_townActionId == 1 && (_drawFrameIndex == 4 || _drawFrameIndex == 13)) sound.playFX(45); - if (_townActionId == 5 && _townCurrent == 23) { + if (_townActionId == 5 && _drawFrameIndex == 23) { File f("spit1.voc"); sound.playSample(&f, 0); } } else { - if (_townMaxId == 32 || _townCurrent == 0) - _townCurrent = 17; - if (_townMaxId == 26 || _townCurrent == 0) - _townCurrent = 20; - if (_townActionId == 1 && (_townCurrent == 3 || _townCurrent == 9)) + if (_townMaxId == 32 && _drawFrameIndex == 0) + _drawFrameIndex = 17; + if (_townMaxId == 26 && _drawFrameIndex == 0) + _drawFrameIndex = 20; + if (_townActionId == 1 && (_drawFrameIndex == 3 || _drawFrameIndex == 9)) sound.playFX(45); } diff --git a/engines/xeen/town.h b/engines/xeen/town.h index e28d03cf5c..af3f4c3a56 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -41,7 +41,6 @@ private: Common::Array<SpriteResource> _townSprites; int _townMaxId; int _townActionId; - int _townCurrent; int _v1, _v2; int _donation; int _healCost; @@ -60,6 +59,7 @@ private: int _currentCharLevel; bool _flag1; uint _nextExperienceLevel; + int _drawFrameIndex; int _drawCtr1, _drawCtr2; void loadStrings(const Common::String &name); -- cgit v1.2.3 From 16b8382d6e72c72d567b44bca8cf0d48a4280366 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 28 Jan 2015 20:09:15 -0500 Subject: XEEN: Fix display of buy message for buying tavern food --- engines/xeen/screen.cpp | 9 +++++++++ engines/xeen/town.cpp | 1 + 2 files changed, 10 insertions(+) (limited to 'engines/xeen') diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 87062dc5ec..e979143ed5 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -63,6 +63,15 @@ void Window::open2() { addDirtyRect(_bounds); frame(); fill(); + + Screen &screen = *_vm->_screen; + screen._writePos.x = _bounds.right - 8; + screen.writeSymbol(19); + + screen._writePos.x = _innerBounds.left; + screen._writePos.y = _innerBounds.top; + screen._fontJustify = JUSTIFY_NONE; + screen._fontReduced = false; } void Window::frame() { diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index a1b09712c5..b28300f2a3 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -659,6 +659,7 @@ Character *Town::doTavernOptions(Character *c) { screen._windows[10].close(); screen._windows[12].open(); screen._windows[12].writeString(msg); + screen._windows[12].update(); if (YesNo::show(_vm, false, true)) { if (party._food >= _v22) { -- cgit v1.2.3 From 1f28332b2053f2dbbe138937f9b0e342774a4cc9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 28 Jan 2015 20:59:01 -0500 Subject: XEEN: Add saving/restoring of background when opening/closing windows --- engines/xeen/screen.cpp | 18 +++++++++++++++--- engines/xeen/screen.h | 1 + 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index e979143ed5..9c9783ba4c 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -60,11 +60,17 @@ void Window::open() { } void Window::open2() { + Screen &screen = *_vm->_screen; + + // Save a copy of the area under the window + _savedArea.create(_bounds.width(), _bounds.height()); + _savedArea.copyRectToSurface(screen, 0, 0, _bounds); + + // Mark the area as dirty and fill it with a default background addDirtyRect(_bounds); frame(); fill(); - Screen &screen = *_vm->_screen; screen._writePos.x = _bounds.right - 8; screen.writeSymbol(19); @@ -130,11 +136,17 @@ void Window::frame() { } void Window::close() { + Screen &screen = *_vm->_screen; + if (_enabled) { - // Update any remaining pending changes to the screen and free - // the window's internal surface storage + // Update the window update(); + // Restore the saved original content + screen.copyRectToSurface(_savedArea, _bounds.left, _bounds.top, + Common::Rect(0, 0, _bounds.width(), _bounds.height())); + addDirtyRect(_bounds); + // Remove the window from the stack and flag it as now disabled for (uint i = 0; i < _vm->_screen->_windowStack.size(); ++i) { if (_vm->_screen->_windowStack[i] == this) diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 85affe3aa2..e3ced06236 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -61,6 +61,7 @@ private: XeenEngine *_vm; Common::Rect _bounds; Common::Rect _innerBounds; + XSurface _savedArea; int _a; int _border; int _xLo, _xHi; -- cgit v1.2.3 From 60c462bfdcb9cb342ccb3367b64c599144f70e57 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 28 Jan 2015 20:59:36 -0500 Subject: XEEN: Fixes for tavern options --- engines/xeen/dialogs_yesno.cpp | 10 +++++----- engines/xeen/dialogs_yesno.h | 4 ++-- engines/xeen/interface.h | 1 - engines/xeen/scripts.cpp | 2 +- engines/xeen/town.cpp | 7 +++++++ engines/xeen/town.h | 2 ++ 6 files changed, 17 insertions(+), 9 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp index 1c0c3a7fe2..8ea27ebd6c 100644 --- a/engines/xeen/dialogs_yesno.cpp +++ b/engines/xeen/dialogs_yesno.cpp @@ -33,7 +33,7 @@ bool YesNo::show(XeenEngine *vm, bool type, bool v2) { return result; } -bool YesNo::execute(bool type, int v2) { +bool YesNo::execute(bool type, bool townFlag) { Screen &screen = *_vm->_screen; EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; @@ -64,12 +64,12 @@ bool YesNo::execute(bool type, int v2) { while (!_vm->shouldQuit()) { events.updateGameCounter(); - if (intf._townSprites[0].empty()) { + if (town.isActive()) { + town.drawTownAnim(townFlag); + numFrames = 3; + } else { intf.draw3d(true); numFrames = 1; - } else { - town.drawTownAnim(v2); - numFrames = 3; } events.wait(3, true); diff --git a/engines/xeen/dialogs_yesno.h b/engines/xeen/dialogs_yesno.h index d083cd64d4..96c3592d9d 100644 --- a/engines/xeen/dialogs_yesno.h +++ b/engines/xeen/dialogs_yesno.h @@ -33,9 +33,9 @@ private: YesNo(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} - bool execute(bool type, int v2); + bool execute(bool type, bool townFlag); public: - static bool show(XeenEngine *vm, bool type, bool v2); + static bool show(XeenEngine *vm, bool type, bool townFlag = false); }; } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 1630e80f69..73cd50977b 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -76,7 +76,6 @@ private: bool checkMoveDirection(int key); public: - SpriteResource _townSprites[8]; int _intrIndex1; Common::String _interfaceText; public: diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 11f88044f5..3ba6329b70 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -1079,7 +1079,7 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { v = ps._luck._temporary; break; case 44: - v = YesNo::show(_vm, mask, false); + v = YesNo::show(_vm, mask); v = (!v && !mask) ? 2 : mask; break; case 45: diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index b28300f2a3..303ef50699 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -1249,6 +1249,13 @@ void Town::drawTownAnim(bool flag) { screen._windows[3].update(); } +/** + * Returns true if a town location (bank, blacksmith, etc.) is currently active + */ +bool Town::isActive() const { + return _townSprites.size() > 0 && !_townSprites[0].empty(); +} + Character *Town::showItems(Character *c, int v2) { error("TODO: showItems"); } diff --git a/engines/xeen/town.h b/engines/xeen/town.h index af3f4c3a56..f6c67ab102 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -109,6 +109,8 @@ public: int townAction(int actionId); void drawTownAnim(bool flag); + + bool isActive() const; }; } // End of namespace Xeen -- cgit v1.2.3 From e34429207c9d632a1f72680a08409992e81d95a5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 28 Jan 2015 21:11:46 -0500 Subject: XEEN: Add missing c_str to a Common::String::format call --- engines/xeen/town.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 303ef50699..f90ffbd481 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -688,7 +688,7 @@ Character *Town::doTavernOptions(Character *c) { } Common::String msg = Common::String::format("\x03""c\x0B""012%s", - _textStrings[(party._day % 10) + idx]); + _textStrings[(party._day % 10) + idx].c_str()); Window &w = screen._windows[12]; w.open(); w.writeString(msg); -- cgit v1.2.3 From be327cb7672652a44294a13b9fa4215ae6358b6a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 29 Jan 2015 08:42:31 -0500 Subject: XEEN: Implemented setSpellText for spells dialog --- engines/xeen/module.mk | 1 + engines/xeen/party.cpp | 7 +++-- engines/xeen/party.h | 2 +- engines/xeen/resources.cpp | 70 ++++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/resources.h | 18 ++++++++++++ engines/xeen/spells.cpp | 12 ++++++++ engines/xeen/spells.h | 7 +++++ engines/xeen/town.cpp | 12 +++----- engines/xeen/town.h | 2 -- 9 files changed, 117 insertions(+), 14 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index c361c472cf..9d252b14c2 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -11,6 +11,7 @@ MODULE_OBJS := \ dialogs_error.o \ dialogs_options.o \ dialogs_input.o \ + dialogs_spells.o \ dialogs_whowill.o \ dialogs_yesno.o \ events.o \ diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 66ba405909..2138ca6154 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -27,6 +27,7 @@ #include "xeen/files.h" #include "xeen/resources.h" #include "xeen/saves.h" +#include "xeen/spells.h" #include "xeen/xeen.h" namespace Xeen { @@ -52,7 +53,7 @@ Character::Character() { _tempAge = 0; Common::fill(&_skills[0], &_skills[18], 0); Common::fill(&_awards[0], &_awards[128], false); - Common::fill(&_spells[9], &_spells[312], false); + Common::fill(&_spells[0], &_spells[39], 0); _lloydMap = 0; _hasSpells = false; _currentSpell = 0; @@ -110,8 +111,8 @@ void Character::synchronize(Common::Serializer &s) { } // Synchronize spell list - SavesManager::syncBitFlags(s, &_spells[0], &_spells[312]); - + for (int i = 0; i < MAX_SPELLS_PER_CLASS - 1; ++i) + s.syncAsByte(_spells[i]); s.syncAsByte(_lloydMap); s.syncAsByte(_lloydPosition.x); s.syncAsByte(_lloydPosition.y); diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 10f4027dfe..035e76c098 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -108,7 +108,7 @@ public: int _tempAge; int _skills[18]; bool _awards[128]; - bool _spells[312]; + int _spells[39]; int _lloydMap; Common::Point _lloydPosition; bool _hasSpells; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 5eec5be89e..57e16d74d0 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -713,4 +713,74 @@ const char *const AMOUNT = "\x03""c\x09""000\x0B""051Amount\x03l\n"; const char *const FOOD_PACKS_FULL = "\v007Your food packs are already full!"; +const char *const BUY_SPELLS = + "\x03""c\x0B""027\x09""039%s\x03l\x0B""046\n" + "\x09""012\x0C""37B\x0C""duy Spells\n" + "\x09""012\x0C""37S\x0C""dpell Info"; + +const char *const GUILD_OPTIONS = + "\x0D\x0C""00\x03""c\x0B""000\x09""000Guild Options for%s" + "\x03l\x09""000\x0B""090Gold" + "\x03r\x09""000%s\x02\x03""c\x0B""122\x09""040ESC\x01"; + +const int SPELL_COSTS[77] = { + 8, 1, 5, -2, 5, -2, 20, 10, 12, 8, 3, + - 3, 75, 40, 12, 6, 200, 10, 100, 30, -1, 30, + 15, 25, 10, -2, 1, 2, 7, 20, -2, -2, 100, + 15, 5, 100, 35, 75, 5, 20, 4, 5, 1, -2, + 6, 2, 75, 40, 60, 6, 4, 25, -2, -2, 60, + - 1, 50, 15, 125, 2, -1, 3, -1, 200, 35, 150, + 15, 5, 4, 10, 8, 30, 4, 5, 7, 5, 0 +}; + +const int DARK_SPELL_RANGES[12][2] = { + { 0, 20 }, { 16, 35 }, { 27, 37 }, { 29, 39 }, + { 0, 17 }, { 14, 34 }, { 26, 37 }, { 29, 39 }, + { 0, 20 }, { 16, 35 }, { 27, 37 }, { 29, 39 } +}; + +const int CLOUDS_SPELL_OFFSETS[5][20] = { + { + 1, 10, 20, 26, 27, 38, 40, 42, 45, 50, + 55, 59, 60, 61, 62, 68, 72, 75, 77, 77 + }, { + 3, 4, 5, 14, 15, 25, 30, 31, 34, 41, + 49, 51, 53, 67, 73, 75, -1, -1, -1, -1 + }, { + 4, 8, 9, 12, 13, 22, 23, 24, 28, 34, + 41, 44, 52, 70, 73, 74, -1, -1, -1, -1 + }, { + 6, 7, 9, 11, 12, 13, 17, 21, 22, 24, + 29, 36, 56, 58, 64, 71, -1, -1, -1, -1 + }, { + 6, 7, 9, 11, 12, 13, 18, 21, 29, 32, + 36, 37, 46, 51, 56, 58, 69, -1, -1, -1 + } +}; + +const int DARK_SPELL_OFFSETS[3][39] = { + { + 42, 1, 26, 59, 27, 10, 50, 68, 55, 62, 67, 73, 2, + 5, 3, 31, 30, 52, 49, 28, 74, 0, 9, 7, 14, 8, + 33, 6, 23, 71, 64, 56, 48, 46, 12, 32, 58, 65, 16 + }, { + 42, 1, 45, 61, 72, 40, 20, 60, 38, 41, 75, 34, 4, + 43, 25, 53, 44, 15, 70, 17, 24, 69, 22, 66, 57, 11, + 29, 39, 51, 21, 19, 36, 47, 13, 54, 37, 18, 35, 63 + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38 + } +}; + +const int SPELL_GEM_COST[77] = { + 0, 0, 2, 1, 2, 4, 5, 0, 0, 0, 0, 10, 10, 10, 0, 0, 20, 4, 10, 20, 1, 10, + 5, 5, 4, 2, 0, 0, 0, 10, 3, 1, 20, 4, 0, 20, 10, 10, 1, 10, 0, 0, 0, 2, + 2, 0, 10, 10, 10, 0, 0, 10, 3, 2, 10, 1, 10, 10, 20, 0, 0, 1, 1, 20, 5, 20, + 5, 0, 0, 0, 0, 5, 1, 2, 0, 2, 0 +}; + +extern const char *NOT_A_SPELL_CASTER = "Not a spell caster..."; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 497b02515b..60f4848c00 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -210,6 +210,24 @@ extern const char *const AMOUNT; extern const char *const FOOD_PACKS_FULL; +extern const char *const BUY_SPELLS; + +extern const char *const GUILD_OPTIONS; + +extern const int SPELL_COSTS[77]; + +extern const int CLOUDS_SPELL_OFFSETS[5][20]; + +extern const int DARK_SPELL_OFFSETS[3][39]; + +extern const int DARK_SPELL_RANGES[12][2]; + +extern const int SPELL_LEVEL_OFFSETS[3][39]; + +extern const int SPELL_GEM_COST[77]; + +extern const char *NOT_A_SPELL_CASTER; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 29c22b1e0b..922f6fcb84 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -22,6 +22,7 @@ #include "xeen/spells.h" #include "xeen/files.h" +#include "xeen/resources.h" #include "xeen/xeen.h" namespace Xeen { @@ -42,4 +43,15 @@ void Spells::load() { f2.close(); } +int Spells::calcSpellCost(int spellId, int expenseFactor) const { + int amount = SPELL_COSTS[spellId]; + return (amount >= 0) ? (amount * 100) << expenseFactor : + (amount * -500) << expenseFactor; +} + +int Spells::calcSpellPoints(int spellId, int expenseFactor) const { + int amount = SPELL_COSTS[spellId]; + return (amount >= 0) ? amount : amount * -1 * expenseFactor; +} + } // End of namespace Xeen diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h index 48c0f9a897..97e3c80bba 100644 --- a/engines/xeen/spells.h +++ b/engines/xeen/spells.h @@ -30,6 +30,8 @@ namespace Xeen { class XeenEngine; +#define MAX_SPELLS_PER_CLASS 40 + class Spells { private: XeenEngine *_vm; @@ -40,6 +42,11 @@ public: Common::StringArray _maeNames; public: Spells(XeenEngine *vm); + + int calcSpellCost(int spellId, int expenseFactor) const; + + int calcSpellPoints(int spellId, int expenseFactor) const; + }; } // End of namespace Xeen diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index f90ffbd481..d773f6d4f2 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -23,6 +23,7 @@ #include "xeen/town.h" #include "xeen/dialogs_input.h" #include "xeen/dialogs_yesno.h" +#include "xeen/dialogs_spells.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -563,15 +564,14 @@ Character *Town::doGuildOptions(Character *c) { sound.playSample(&f, 1); } } - } - else if (_buttonValue == Common::KEYCODE_s) { + } else if (_buttonValue == Common::KEYCODE_s) { if (c->guildMember()) - c = showAvailableSpells(c, 0x80); + c = SpellsScroll::show(_vm, c, 0x80); _buttonValue = 0; } else if (_buttonValue == Common::KEYCODE_c) { if (!c->noActions()) { if (c->guildMember()) - c = showAvailableSpells(c, 0); + c = SpellsScroll::show(_vm, c, 0); _buttonValue = 0; } } @@ -1260,8 +1260,4 @@ Character *Town::showItems(Character *c, int v2) { error("TODO: showItems"); } -Character *Town::showAvailableSpells(Character *c, int v2) { - error("TODO: showAvailableSpells"); -} - } // End of namespace Xeen diff --git a/engines/xeen/town.h b/engines/xeen/town.h index f6c67ab102..27b1fe2121 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -101,8 +101,6 @@ private: int subtract(int mode, uint amount, int whereId, ErrorWaitType wait); Character *showItems(Character *c, int v2); - - Character *showAvailableSpells(Character *c, int v2); public: Town(XeenEngine *vm); -- cgit v1.2.3 From 29753a29a4b82d8cac78223232dc84c003d8f210 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 30 Jan 2015 19:18:43 -0500 Subject: XEEN: Implemented SpellsDialog and ConfirmDialog classes --- engines/xeen/dialogs_confirm.cpp | 85 ++++++++ engines/xeen/dialogs_confirm.h | 43 ++++ engines/xeen/dialogs_spells.cpp | 416 +++++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_spells.h | 61 ++++++ engines/xeen/dialogs_yesno.cpp | 4 +- engines/xeen/module.mk | 1 + engines/xeen/party.cpp | 66 +++++++ engines/xeen/party.h | 5 + engines/xeen/resources.cpp | 47 ++++- engines/xeen/resources.h | 20 +- engines/xeen/spells.cpp | 2 + engines/xeen/spells.h | 1 + engines/xeen/town.cpp | 86 +------- engines/xeen/town.h | 4 - 14 files changed, 755 insertions(+), 86 deletions(-) create mode 100644 engines/xeen/dialogs_confirm.cpp create mode 100644 engines/xeen/dialogs_confirm.h create mode 100644 engines/xeen/dialogs_spells.cpp create mode 100644 engines/xeen/dialogs_spells.h (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_confirm.cpp b/engines/xeen/dialogs_confirm.cpp new file mode 100644 index 0000000000..13a41e76ca --- /dev/null +++ b/engines/xeen/dialogs_confirm.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 "xeen/dialogs_confirm.h" +#include "xeen/xeen.h" + +namespace Xeen { + +bool ConfirmDialog::show(XeenEngine *vm, const Common::String &msg, int v2) { + ConfirmDialog *dlg = new ConfirmDialog(vm); + bool result = dlg->execute(msg, v2); + delete dlg; + + return result; +} + +bool ConfirmDialog::execute(const Common::String &msg, int v2) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + SpriteResource confirmSprites; + confirmSprites.load("confirm.icn"); + + addButton(Common::Rect(129, 112, 153, 132), Common::KEYCODE_y, &confirmSprites); + addButton(Common::Rect(185, 112, 209, 132), Common::KEYCODE_n, &confirmSprites); + + Window &w = screen._windows[v2 ? 21 : 22]; + w.open(); + + if (v2) { + confirmSprites.draw(screen._windows[21], 0, Common::Point(129, 112)); + confirmSprites.draw(screen._windows[21], 2, Common::Point(185, 112)); + + _buttons[0]._bounds.moveTo(129, 112); + _buttons[1]._bounds.moveTo(185, 112); + } else if (v2 & 0x80) { + clearButtons(); + } else { + confirmSprites.draw(screen._windows[22], 0, Common::Point(120, 133)); + confirmSprites.draw(screen._windows[22], 2, Common::Point(176, 133)); + + _buttons[0]._bounds.moveTo(120, 133); + _buttons[1]._bounds.moveTo(176, 133); + } + + w.writeString(msg); + w.update(); + + bool result = false; + while (!_vm->shouldQuit()) { + while (!events.isKeyMousePressed()) + events.pollEventsAndWait(); + + if ((v2 & 0x80) || _buttonValue == Common::KEYCODE_ESCAPE || + _buttonValue == Common::KEYCODE_y) + break; + else if (_buttonValue == Common::KEYCODE_y) { + result = true; + break; + } + } + + w.close(); + return result; +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_confirm.h b/engines/xeen/dialogs_confirm.h new file mode 100644 index 0000000000..825be5e764 --- /dev/null +++ b/engines/xeen/dialogs_confirm.h @@ -0,0 +1,43 @@ +/* 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 XEEN_DIALOGS_CONFIRM_H +#define XEEN_DIALOGS_CONFIRM_H + +#include "xeen/dialogs.h" + +namespace Xeen { + +class ConfirmDialog : public ButtonContainer { +private: + XeenEngine *_vm; + + ConfirmDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + bool execute(const Common::String &msg, int v2); +public: + static bool show(XeenEngine *vm, const Common::String &msg, int v2); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_CONFIRM_H */ diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp new file mode 100644 index 0000000000..7ae5e7ad90 --- /dev/null +++ b/engines/xeen/dialogs_spells.cpp @@ -0,0 +1,416 @@ +/* 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 "xeen/dialogs_spells.h" +#include "xeen/dialogs_confirm.h" +#include "xeen/resources.h" +#include "xeen/spells.h" +#include "xeen/sprites.h" +#include "xeen/xeen.h" + +namespace Xeen { + +Character *SpellsScroll::show(XeenEngine *vm, Character *c, int v2) { + SpellsScroll *dlg = new SpellsScroll(vm); + Character *result = dlg->execute(c, v2); + delete dlg; + + return result; +} + +Character *SpellsScroll::execute(Character *c, int v2) { + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + Spells &spells = *_vm->_spells; + bool isDarkCc = _vm->_files->_isDarkCc; + loadButtons(); + + int v2Copy = v2; + v2 &= 0x7f; + int selection = -1; + int topIndex = 0; + int newSelection; + screen._windows[25].open(); + + while (!_vm->shouldQuit()) { + if (!v2) { + if (!c->guildMember()) { + sound.playSample(nullptr, 0); + intf._overallFrame = 5; + File f(isDarkCc ? "skull1.voc" : "guild11.voc"); + sound.playSample(&f, 1); + break; + } + + Common::String title = Common::String::format(BUY_SPELLS, c->_name.c_str()); + Common::String msg = Common::String::format(GUILD_OPTIONS, + title.c_str(), XeenEngine::printMil(party._gold)); + screen._windows[10].writeString(msg); + + warning("TODO: Sprite draw using previously used button sprites"); + } + + _spells.clear(); + const char *errorMsg = setSpellText(c, v2Copy); + screen._windows[25].writeString(Common::String::format(SPELLS_FOR, + errorMsg == nullptr ? SPELL_LINES_0_TO_9 : nullptr)); + + screen._windows[37].writeString(Common::String::format(SPELLS_DIALOG_SPELLS, + (topIndex + 0) < _spells.size() ? _spells[topIndex + 0]._name.c_str() : nullptr, + (topIndex + 1) < _spells.size() ? _spells[topIndex + 1]._name.c_str() : nullptr, + (topIndex + 2) < _spells.size() ? _spells[topIndex + 2]._name.c_str() : nullptr, + (topIndex + 3) < _spells.size() ? _spells[topIndex + 3]._name.c_str() : nullptr, + (topIndex + 4) < _spells.size() ? _spells[topIndex + 4]._name.c_str() : nullptr, + (topIndex + 5) < _spells.size() ? _spells[topIndex + 5]._name.c_str() : nullptr, + (topIndex + 6) < _spells.size() ? _spells[topIndex + 6]._name.c_str() : nullptr, + (topIndex + 7) < _spells.size() ? _spells[topIndex + 7]._name.c_str() : nullptr, + (topIndex + 8) < _spells.size() ? _spells[topIndex + 8]._name.c_str() : nullptr, + (topIndex + 9) < _spells.size() ? _spells[topIndex + 9]._name.c_str() : nullptr, + v2 ? SPELL_PTS : GOLD, + v2 ? c->_currentSp : party._gold + )); + + _iconSprites.draw(screen, 4, Common::Point(39, 26)); + _iconSprites.draw(screen, 0, Common::Point(187, 26)); + _iconSprites.draw(screen, 2, Common::Point(187, 111)); + if (v2) + _iconSprites.draw(screen._windows[25], 5, Common::Point(132, 123)); + + screen._windows[25].update(); + + while (!_vm->shouldQuit() && !events.isKeyMousePressed()) + events.pollEventsAndWait(); + if (_vm->shouldQuit()) + break; + checkEvents(_vm); + + switch (_buttonValue) { + case Common::KEYCODE_F1: + case Common::KEYCODE_F6: + if (_vm->_mode != MODE_2) { + _buttonValue -= Common::KEYCODE_F1; + if (_buttonValue < party._partyCount) { + c = &party._activeParty[_buttonValue]; + spells._lastCaster = _buttonValue; + intf.highlightChar(_buttonValue); + + if (_vm->_mode == MODE_17) { + screen._windows[10].writeString(Common::String::format(GUILD_OPTIONS, + XeenEngine::printMil(party._gold).c_str(), GUILD_TEXT, c->_name.c_str())); + } else { + int category; + switch (c->_class) { + case CLASS_ARCHER: + case CLASS_SORCERER: + category = 1; + break; + case CLASS_DRUID: + case CLASS_RANGER: + category = 2; + break; + default: + category = 0; + break; + } + + int spellIndex = (c->_currentSp == -1) ? 39 : c->_currentSpell; + int spellId = SPELLS_ALLOWED[category][spellIndex]; + screen._windows[10].writeString(Common::String::format(SPELL_DETAILS, + spells._spellNames[spellId].c_str(), + spells.calcSpellPoints(spellId, c->getCurrentLevel()), + SPELL_GEM_COST[spellId], c->_currentSp)); + } + + drawButtons(&screen); + screen._windows[10].update(); + } + } + break; + + case Common::KEYCODE_RETURN: + case Common::KEYCODE_KP_ENTER: + case Common::KEYCODE_s: + if (selection != -1) + _buttonValue = Common::KEYCODE_ESCAPE; + break; + + case Common::KEYCODE_ESCAPE: + selection = -1; + _buttonValue = Common::KEYCODE_ESCAPE; + break; + + case Common::KEYCODE_0: + case Common::KEYCODE_1: + case Common::KEYCODE_2: + case Common::KEYCODE_3: + case Common::KEYCODE_4: + case Common::KEYCODE_5: + case Common::KEYCODE_6: + case Common::KEYCODE_7: + case Common::KEYCODE_8: + case Common::KEYCODE_9: + newSelection = topIndex + (_buttonValue == Common::KEYCODE_0) ? 9 : + (_buttonValue - Common::KEYCODE_1); + + if (newSelection < (int)_spells.size()) { + int expenseFactor = 0; + int category = 0; + + switch (c->_class) { + case CLASS_PALADIN: + expenseFactor = 1; + category = 0; + break; + case CLASS_ARCHER: + expenseFactor = 1; + category = 1; + break; + case CLASS_CLERIC: + category = 0; + break; + case CLASS_SORCERER: + category = 1; + break; + case CLASS_DRUID: + category = 2; + break; + case CLASS_RANGER: + expenseFactor = 1; + category = 2; + break; + default: + break; + } + + int spellId = _spells[newSelection]._spellId; + int spellIndex = _spells[newSelection]._spellIndex; + int spellCost = spells.calcSpellCost(spellId, expenseFactor); + if (v2) { + // TODO: Confirm this refactoring against against original + selection = _buttonValue; + } else { + Common::String spellName = _spells[_buttonValue]._name; + Common::String msg = (v2Copy & 0x80) ? + Common::String::format(SPELLS_PRESS_A_KEY, msg.c_str()) : + Common::String::format(SPELLS_PURCHASE, msg.c_str(), spellCost); + + if (ConfirmDialog::show(_vm, msg, v2Copy + 1)) { + if (party.subtract(0, spellCost, 0, WT_FREEZE_WAIT)) { + ++c->_spells[spellIndex]; + sound.playSample(nullptr, 0); + intf._overallFrame = 0; + File f(isDarkCc ? "guild12.voc" : "parrot2.voc"); + sound.playSample(&f, 1); + } else { + sound.playFX(21); + } + } + } + } + break; + + case Common::KEYCODE_PAGEUP: + case Common::KEYCODE_KP9: + topIndex = MAX(topIndex - 10, 0); + break; + + case Common::KEYCODE_PAGEDOWN: + case Common::KEYCODE_KP3: + topIndex = MIN(topIndex + 10, (((int)_spells.size() - 1) / 10) * 10); + break; + + case Common::KEYCODE_UP: + case Common::KEYCODE_KP8: + if (topIndex > 0) + --topIndex; + break; + + case Common::KEYCODE_DOWN: + case Common::KEYCODE_KP2: + if (topIndex < ((int)_spells.size() - 10)) + ++topIndex; + break; + } + } + + screen._windows[25].close(); + if (v2 && selection != -1) + c->_currentSpell = _spells[selection]._spellIndex; + + return c; +} + +void SpellsScroll::loadButtons() { + _iconSprites.load("main.icn"); + _scrollSprites.load("scroll.icn"); + addButton(Common::Rect(187, 26, 198, 36), Common::KEYCODE_UP, &_scrollSprites, true); + addButton(Common::Rect(187, 111, 198, 121), Common::KEYCODE_DOWN, &_scrollSprites, true); + addButton(Common::Rect(40, 28, 187, 36), Common::KEYCODE_1, &_scrollSprites, false); + addButton(Common::Rect(40, 37, 187, 45), Common::KEYCODE_2, &_scrollSprites, false); + addButton(Common::Rect(40, 46, 187, 54), Common::KEYCODE_3, &_scrollSprites, false); + addButton(Common::Rect(40, 55, 187, 63), Common::KEYCODE_4, &_scrollSprites, false); + addButton(Common::Rect(40, 64, 187, 72), Common::KEYCODE_5, &_scrollSprites, false); + addButton(Common::Rect(40, 73, 187, 81), Common::KEYCODE_6, &_scrollSprites, false); + addButton(Common::Rect(40, 82, 187, 90), Common::KEYCODE_7, &_scrollSprites, false); + addButton(Common::Rect(40, 91, 187, 99), Common::KEYCODE_8, &_scrollSprites, false); + addButton(Common::Rect(40, 100, 187, 108), Common::KEYCODE_9, &_scrollSprites, false); + addButton(Common::Rect(40, 109, 187, 117), Common::KEYCODE_0, &_scrollSprites, false); + addButton(Common::Rect(174, 123, 198, 133), Common::KEYCODE_ESCAPE, &_scrollSprites, false); + addButton(Common::Rect(187, 35, 198, 73), Common::KEYCODE_PAGEUP, &_scrollSprites, false); + addButton(Common::Rect(187, 74, 198, 112), Common::KEYCODE_PAGEDOWN, &_scrollSprites, false); + addButton(Common::Rect(132, 123, 168, 133), Common::KEYCODE_s, &_scrollSprites, false); +} + +const char *SpellsScroll::setSpellText(Character *c, int v2) { + Party &party = *_vm->_party; + Spells &spells = *_vm->_spells; + bool isDarkCc = _vm->_files->_isDarkCc; + int expenseFactor = 0; + int currLevel = c->getCurrentLevel(); + int category; + + if ((v2 & 0x7f) == 0) { + switch (c->_class) { + case CLASS_PALADIN: + expenseFactor = 1; + category = 0; + break; + case CLASS_ARCHER: + expenseFactor = 1; + category = 1; + break; + case CLASS_CLERIC: + category = 0; + break; + case CLASS_SORCERER: + category = 1; + break; + case CLASS_DRUID: + category = 2; + break; + case CLASS_RANGER: + expenseFactor = 1; + category = 2; + break; + default: + category = -1; + break; + } + + if (category != -1) { + if (party._mazeId == 49 || party._mazeId == 37) { + for (int spellId = 0; spellId < 76; ++spellId) { + int idx = 0; + while (idx < MAX_SPELLS_PER_CLASS && SPELLS_ALLOWED[category][idx] == spellId) + ++idx; + + // Handling if the spell is appropriate for the character's class + if (idx < MAX_SPELLS_PER_CLASS) { + if (!c->_spells[idx] || (v2 & 0x80)) { + int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor); + _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u", + spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), + idx, spellId)); + } + } + } + } else if (isDarkCc) { + int groupIndex = (party._mazeId - 29) / 2; + for (int spellId = DARK_SPELL_RANGES[category][0]; + spellId < DARK_SPELL_RANGES[category][1]; ++spellId) { + int idx = 0; + while (idx < 40 && SPELLS_ALLOWED[category][idx] == + DARK_SPELL_OFFSETS[category][spellId]); + + if (idx < 40) { + if (!c->_spells[idx] || (v2 & 0x80)) { + int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor); + _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u", + spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), + idx, spellId)); + } + } + } + } else { + for (int spellId = 0; spellId < 20; ++spellId) { + int idx = 0; + while (CLOUDS_SPELL_OFFSETS[party._mazeId - 29][spellId] != + SPELLS_ALLOWED[category][idx] && idx < 40) ; + + if (idx < 40) { + if (!c->_spells[idx] || (v2 & 0x80)) { + int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor); + _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u", + spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), + idx, spellId)); + } + } + } + } + } + + if (c->getMaxSP() == 0) + return NOT_A_SPELL_CASTER; + + } else if ((v2 & 0x7f) == 1) { + switch (c->_class) { + case 0: + case 12: + category = 0; + break; + case 1: + case 3: + category = 1; + break; + case 7: + case 8: + category = 2; + break; + default: + category = 0; + break; + } + + if (c->getMaxSP() == 0) { + return NOT_A_SPELL_CASTER; + } else { + for (int spellIndex = 0; spellIndex < (MAX_SPELLS_PER_CLASS - 1); ++spellIndex) { + if (c->_spells[spellIndex]) { + int spellId = SPELLS_ALLOWED[category][spellIndex]; + int gemCost = SPELL_GEM_COST[spellId]; + int spCost = spells.calcSpellPoints(spellId, currLevel); + + Common::String msg = Common::String::format("\x3l%s\x3r\x9""000%u/%u", + spells._spellNames[spellId].c_str(), spCost, gemCost); + _spells.push_back(SpellEntry(msg, spellIndex, spellId)); + } + } + } + } + + return nullptr; +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h new file mode 100644 index 0000000000..69e339fa79 --- /dev/null +++ b/engines/xeen/dialogs_spells.h @@ -0,0 +1,61 @@ +/* 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 XEEN_DIALOGS_SPELLS_H +#define XEEN_DIALOGS_SPELLS_H + +#include "common/array.h" +#include "xeen/dialogs.h" +#include "xeen/party.h" + +namespace Xeen { + +struct SpellEntry { + Common::String _name; + int _spellIndex; + int _spellId; + + SpellEntry(const Common::String &name, int spellIndex, int spellId) : + _name(name), _spellIndex(spellIndex), _spellId(spellId) {} +}; + +class SpellsScroll : public ButtonContainer { +private: + XeenEngine *_vm; + SpriteResource _iconSprites; + SpriteResource _scrollSprites; + Common::Array<SpellEntry> _spells; + + SpellsScroll(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + Character *execute(Character *c, int v2); + + void loadButtons(); + + const char *setSpellText(Character *c, int v2); +public: + static Character *show(XeenEngine *vm, Character *c, int v2); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_SPELLS_H */ diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp index 8ea27ebd6c..17ca9a0c3e 100644 --- a/engines/xeen/dialogs_yesno.cpp +++ b/engines/xeen/dialogs_yesno.cpp @@ -25,9 +25,9 @@ namespace Xeen { -bool YesNo::show(XeenEngine *vm, bool type, bool v2) { +bool YesNo::show(XeenEngine *vm, bool type, bool townFlag) { YesNo *dlg = new YesNo(vm); - bool result = dlg->execute(type, v2); + bool result = dlg->execute(type, townFlag); delete dlg; return result; diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 9d252b14c2..be951239d3 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -8,6 +8,7 @@ MODULE_OBJS := \ debugger.o \ detection.o \ dialogs.o \ + dialogs_confirm.o \ dialogs_error.o \ dialogs_options.o \ dialogs_input.o \ diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 2138ca6154..66078b67e8 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -1218,4 +1218,70 @@ void Party::handleLight() { (map.mazeData()._mazeFlags2 & FLAG_IS_DARK) == 0 ? 4 : 0; } +int Party::subtract(int mode, uint amount, int whereId, ErrorWaitType wait) { + switch (mode) { + case 0: + // Gold + if (whereId) { + if (amount <= _bankGold) { + _bankGold -= amount; + } else { + notEnough(0, whereId, false, wait); + return false; + } + } + else { + if (amount <= _gold) { + _gold -= amount; + } else { + notEnough(0, whereId, false, wait); + return false; + } + } + break; + + case 1: + // Gems + if (whereId) { + if (amount <= _bankGems) { + _bankGems -= amount; + } else { + notEnough(0, whereId, false, wait); + return false; + } + } + else { + if (amount <= _gems) { + _gems -= amount; + } else { + notEnough(0, whereId, false, wait); + return false; + } + } + break; + + case 2: + // Food + if (amount > _food) { + _food -= amount; + } else { + notEnough(5, 0, 0, wait); + return false; + } + break; + + default: + break; + } + + return true; +} + +void Party::notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait) { + Common::String msg = Common::String::format( + mode ? NO_X_IN_THE_Y : NOT_ENOUGH_X_IN_THE_Y, + CONSUMABLE_NAMES[consumableId], WHERE_NAMES[whereId]); + ErrorScroll::show(_vm, msg, wait); +} + } // End of namespace Xeen diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 035e76c098..e00b42476a 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -28,6 +28,7 @@ #include "common/rect.h" #include "common/serializer.h" #include "xeen/combat.h" +#include "xeen/dialogs_error.h" #include "xeen/items.h" namespace Xeen { @@ -274,6 +275,10 @@ public: void resetTemps(); void handleLight(); + + int subtract(int mode, uint amount, int whereId, ErrorWaitType wait); + + void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait); }; } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 57e16d74d0..ed304dc9e1 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -492,7 +492,7 @@ const int MONSTER_EFFECT_FLAGS[15][8] = { { 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108 } }; -const uint SPELLS_ALLOWED[3][40] = { +const int SPELLS_ALLOWED[3][40] = { { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 14, 16, 23, 26, 27, 28, 30, 31, 32, @@ -781,6 +781,49 @@ const int SPELL_GEM_COST[77] = { 5, 0, 0, 0, 0, 5, 1, 2, 0, 2, 0 }; -extern const char *NOT_A_SPELL_CASTER = "Not a spell caster..."; +const char *const NOT_A_SPELL_CASTER = "Not a spell caster..."; + +const char *const SPELLS_FOR = "\xD\xC""d%s\x2\x3""c\x9""000\xB""002Spells for %s"; + +const char *const SPELL_LINES_0_TO_9 = + "\x2\x3l\xB""015\x9""0011\n2\n3\n4\n5\n6\n7\n8\n9\n0"; + +const char *const SPELLS_DIALOG_SPELLS = "\x3l\xB""015" + "\x9""010\xC""%2u%s\xC""d\x3l\n" + "\x9""010\xC""%2u%s\xC""d\x3l\n" + "\x9""010\xC""%2u%s\xC""d\x3l\n" + "\x9""010\xC""%2u%s\xC""d\x3l\n" + "\x9""010\xC""%2u%s\xC""d\x3l\n" + "\x9""010\xC""%2u%s\xC""d\x3l\n" + "\x9""010\xC""%2u%s\xC""d\x3l\n" + "\x9""010\xC""%2u%s\xC""d\x3l\n" + "\x9""010\xC""%2u%s\xC""d\x3l\n" + "\x9""010\xC""%2u%s\xC""d\x3l" + "\x9""004\xB""110%s - %lu\x1"; + +const char *const SPELL_PTS = "Spell Pts"; + +const char *const GOLD = "Gold"; + +const char *const SPELLS_PRESS_A_KEY = + "\x3""c\xC""09%s\xC""d\x3l\n" + "\n" + "%s\x3""c\x9""000\xB""100Press a Key!"; + +const char *const SPELLS_PURCHASE = + "\x3l\xB""000\x9""000\xC""d%s Do you wish to purchase " + "\xC""09%s\xC""d for %u?"; + +const char *const SPELL_DETAILS = +"\xD\x2\x3""c\xB""122\x9""013\xC""37C\xC""dast" +"\x9""040\xC""37N\xC""dew\x9""067ESC\x1""000\xB""000\x3""cCast Spell\n" +"\n" +"%s\x3l\n" +"\n" +"Spell Ready:\x3""c\n" +"\n" +"\xC""09%s\xC""d\x2\x3l\n" +"\xB""082Cost\x3r\x9""000%u/%u\x3l\n" +"Cur SP\x3r\x9""000%u\x1"; } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 60f4848c00..37afb2cc76 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -124,7 +124,7 @@ extern const int COMBAT_FLOAT_Y[8]; extern const int MONSTER_EFFECT_FLAGS[15][8]; -extern const uint SPELLS_ALLOWED[3][40]; +extern const int SPELLS_ALLOWED[3][40]; extern const int BASE_HP_BY_CLASS[10]; @@ -226,7 +226,23 @@ extern const int SPELL_LEVEL_OFFSETS[3][39]; extern const int SPELL_GEM_COST[77]; -extern const char *NOT_A_SPELL_CASTER; +extern const char *const NOT_A_SPELL_CASTER; + +extern const char *const SPELLS_FOR; + +extern const char *const SPELL_LINES_0_TO_9; + +extern const char *const SPELLS_DIALOG_SPELLS; + +extern const char *const SPELL_PTS; + +extern const char *const GOLD; + +extern const char *const SPELLS_PRESS_A_KEY; + +extern const char *const SPELLS_PURCHASE; + +extern const char *const SPELL_DETAILS; } // End of namespace Xeen diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 922f6fcb84..588fa1b510 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -28,6 +28,8 @@ namespace Xeen { Spells::Spells(XeenEngine *vm) : _vm(vm) { + _lastCaster = 0; + load(); } diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h index 97e3c80bba..96f491684e 100644 --- a/engines/xeen/spells.h +++ b/engines/xeen/spells.h @@ -40,6 +40,7 @@ private: public: Common::StringArray _spellNames; Common::StringArray _maeNames; + int _lastCaster; public: Spells(XeenEngine *vm); diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index d773f6d4f2..2f31113146 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -606,7 +606,7 @@ Character *Town::doTavernOptions(Character *c) { case Common::KEYCODE_d: // Drink if (!c->noActions()) { - if (subtract(0, 1, 0, WT_2)) { + if (party.subtract(0, 1, 0, WT_2)) { sound.playSample(nullptr, 0); File f("gulp.voc"); sound.playSample(&f, 0); @@ -664,7 +664,7 @@ Character *Town::doTavernOptions(Character *c) { if (YesNo::show(_vm, false, true)) { if (party._food >= _v22) { ErrorScroll::show(_vm, FOOD_PACKS_FULL, WT_2); - } else if (subtract(0, _v23, 0, WT_2)) { + } else if (party.subtract(0, _v23, 0, WT_2)) { party._food = _v22; sound.playSample(nullptr, 0); File f(isDarkCc ? "thanks2.voc" : "thankyou.voc"); @@ -744,7 +744,7 @@ Character *Town::doTavernOptions(Character *c) { drawButtons(&screen); screen._windows[10].update(); townWait(); - } else if (subtract(0, 1, 0, WT_2)) { + } else if (party.subtract(0, 1, 0, WT_2)) { sound.playSample(nullptr, 0); File f(isDarkCc ? "thanks2.voc" : "thankyou.voc"); sound.playSample(&f, 1); @@ -805,7 +805,7 @@ Character *Town::doTempleOptions(Character *c) { break; case Common::KEYCODE_d: - if (_donation && subtract(0, _donation, 0, WT_2)) { + if (_donation && party.subtract(0, _donation, 0, WT_2)) { sound.playSample(nullptr, 0); File f("coina.voc"); sound.playSample(&f, 1); @@ -832,7 +832,7 @@ Character *Town::doTempleOptions(Character *c) { break; case Common::KEYCODE_h: - if (_healCost && subtract(0, _healCost, 0, WT_2)) { + if (_healCost && party.subtract(0, _healCost, 0, WT_2)) { c->_magicResistence._temporary = 0; c->_energyResistence._temporary = 0; c->_poisonResistence._temporary = 0; @@ -860,7 +860,7 @@ Character *Town::doTempleOptions(Character *c) { break; case Common::KEYCODE_u: - if (_uncurseCost && subtract(0, _uncurseCost, 0, WT_2)) { + if (_uncurseCost && party.subtract(0, _uncurseCost, 0, WT_2)) { for (int idx = 0; idx < 9; ++idx) { c->_weapons[idx]._bonusFlags &= ~FLAG_CURSED; c->_armor[idx]._bonusFlags &= ~FLAG_CURSED; @@ -921,7 +921,7 @@ Character *Town::doTrainingOptions(Character *c) { sound.playSample(&f); } else if (!c->noActions()) { - if (subtract(0, (c->_level._permanent * c->_level._permanent) * 10, 0, WT_2)) { + if (party.subtract(0, (c->_level._permanent * c->_level._permanent) * 10, 0, WT_2)) { _drawFrameIndex = 0; sound.playSample(nullptr, 0); File f(isDarkCc ? "prtygd.voc" : "trainin2.voc"); @@ -1003,14 +1003,14 @@ void Town::depositWithdrawl(int choice) { (choice && !party._bankGold && !flag) || (!choice && !party._gems && flag) || (!choice && !party._gold && !flag)) { - notEnough(flag, choice, 1, WT_2); + party.notEnough(flag, choice, 1, WT_2); } else { screen._windows[35].writeString(AMOUNT); int amount = NumericInput::show(_vm, 35, 10, 77); if (amount) { if (flag) { - if (subtract(true, amount, choice, WT_2)) { + if (party.subtract(true, amount, choice, WT_2)) { if (choice) { party._gems += amount; } else { @@ -1018,7 +1018,7 @@ void Town::depositWithdrawl(int choice) { } } } else { - if (subtract(false, amount, choice, WT_2)) { + if (party.subtract(false, amount, choice, WT_2)) { if (choice) { party._gold += amount; } else { @@ -1053,72 +1053,6 @@ void Town::depositWithdrawl(int choice) { _buttons[2]._value = Common::KEYCODE_ESCAPE; } -void Town::notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait) { - Common::String msg = Common::String::format( - mode ? NO_X_IN_THE_Y : NOT_ENOUGH_X_IN_THE_Y, - CONSUMABLE_NAMES[consumableId], WHERE_NAMES[whereId]); - ErrorScroll::show(_vm, msg, wait); -} - -int Town::subtract(int mode, uint amount, int whereId, ErrorWaitType wait) { - Party &party = *_vm->_party; - - switch (mode) { - case 0: - // Gold - if (whereId) { - if (amount <= party._bankGold) { - party._bankGold -= amount; - } else { - notEnough(0, whereId, false, wait); - return false; - } - } else { - if (amount <= party._gold) { - party._gold -= amount; - } else { - notEnough(0, whereId, false, wait); - return false; - } - } - break; - - case 1: - // Gems - if (whereId) { - if (amount <= party._bankGems) { - party._bankGems -= amount; - } else { - notEnough(0, whereId, false, wait); - return false; - } - } else { - if (amount <= party._gems) { - party._gems -= amount; - } else { - notEnough(0, whereId, false, wait); - return false; - } - } - break; - - case 2: - // Food - if (amount > party._food) { - party._food -= amount; - } else { - notEnough(5, 0, 0, wait); - return false; - } - break; - - default: - break; - } - - return true; -} - void Town::drawTownAnim(bool flag) { Interface &intf = *_vm->_interface; Screen &screen = *_vm->_screen; diff --git a/engines/xeen/town.h b/engines/xeen/town.h index 27b1fe2121..8237f8102e 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -96,10 +96,6 @@ private: void depositWithdrawl(int choice); - void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait); - - int subtract(int mode, uint amount, int whereId, ErrorWaitType wait); - Character *showItems(Character *c, int v2); public: Town(XeenEngine *vm); -- cgit v1.2.3 From 4b364c50d6069e0f94254b78d8ef5839d0e63f04 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 30 Jan 2015 19:59:38 -0500 Subject: XEEN: Fix glitch in indoor walls drawing --- engines/xeen/interface_map.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 77a5f928c7..dcae6cc406 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -27,6 +27,8 @@ namespace Xeen { +static bool debugFlag = false; + OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]), _groundSprite(_data[2]), _combatImgs1(&_data[124]), _combatImgs2(&_data[95]), _combatImgs3(&_data[76]), _combatImgs4(&_data[53]), _groundTiles(&_data[3]) { @@ -189,7 +191,7 @@ IndoorDrawList::IndoorDrawList() : _objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]), _objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]), _combatImgs1(&_data[162]), _combatImgs2(&_data[135]), - _combatImgs3(&_data[111]), _combatImgs4(&_data[80]) { + _combatImgs3(&_data[111]), _combatImgs4(&_data[79]) { // Setup draw structure positions _data[0] = DrawStruct(0, 8, 8); _data[1] = DrawStruct(1, 8, 25); @@ -3699,7 +3701,7 @@ void InterfaceMap::drawIndoors() { if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31]) { if (_wo[33]) - _indoorList._fwl_3F1R._frame = 15; + _indoorList._swl_3F1R._frame = 15; else if (_wo[77]) _indoorList._swl_3F1R._frame = 39; } -- cgit v1.2.3 From 2472cc0917e3e1a56f61e270e55c76af1152cb05 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 31 Jan 2015 07:22:25 -0500 Subject: XEEN: Initial implementation of map dialog --- engines/xeen/dialogs_automap.cpp | 413 +++++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_automap.h | 45 +++++ engines/xeen/interface.cpp | 7 + engines/xeen/interface_map.cpp | 2 +- engines/xeen/map.h | 2 +- engines/xeen/module.mk | 2 + engines/xeen/resources.cpp | 28 +-- engines/xeen/resources.h | 4 + 8 files changed, 490 insertions(+), 13 deletions(-) create mode 100644 engines/xeen/dialogs_automap.cpp create mode 100644 engines/xeen/dialogs_automap.h (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_automap.cpp b/engines/xeen/dialogs_automap.cpp new file mode 100644 index 0000000000..08cf593f7b --- /dev/null +++ b/engines/xeen/dialogs_automap.cpp @@ -0,0 +1,413 @@ +/* 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 "xeen/dialogs_automap.h" +#include "xeen/resources.h" +#include "xeen/xeen.h" + +namespace Xeen { + + +void AutoMapDialog::show(XeenEngine *vm) { + AutoMapDialog *dlg = new AutoMapDialog(vm); + dlg->execute(); + delete dlg; +} + +void AutoMapDialog::execute() { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + int frame2 = intf._overallFrame * 2; + int varSI = 1; + bool frameEndFlag; + + int yDiffStart = 8; + int xDiffStart = 248; + Common::Point pt = party._mazePosition; + Common::Point arrowPt; + SpriteResource globalSprites; + globalSprites.load("global.icn"); + + if (pt.x < 8 && map.mazeData()._surroundingMazes._west == 0) { + arrowPt.x = pt.x * 10 + 4; + } else if (pt.x > 23) { + arrowPt.x = pt.x * 10 + 100; + pt.x = 23; + } else if (pt.x > 8 && map.mazeData()._surroundingMazes._east == 0) { + arrowPt.x = pt.x * 10 + 4; + pt.x = 7; + } else { + arrowPt.x = 74; + } + + if (pt.y < 8 && map.mazeData()._surroundingMazes._south == 0) { + arrowPt.y = ((15 - pt.y) << 3) + 13; + pt.y = 8; + } else if (pt.y > 24) { + arrowPt.y = ((15 - (pt.y - 24)) << 3) + 13; + pt.y = 24; + } else if (pt.y >= 8 && map.mazeData()._surroundingMazes._north == 0) { + arrowPt.y = ((15 - pt.y) << 3) + 13; + pt.y = 8; + } else { + arrowPt.y = 69; + } + + screen._windows[5].open(); + MazeData &mazeData = map.mazeDataCurrent(); + bool drawFlag = true; + int v; + + events.updateGameCounter(); + do { + if (drawFlag) + intf.draw3d(false); + screen._windows[5].writeString("\n"); + + if (map._isOutdoors) { + // Draw outdoors map + for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16; + ++yCtr, --yDiff, yp += 8) { + for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) { + v = map.mazeLookup(Common::Point(xDiff, yDiff), 0); + + if (map._currentSteppedOn) { + map._tileSprites.draw(screen, map.mazeDataCurrent()._surfaceTypes[v], + Common::Point(xp, yp)); + } + } + } + + for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16; + ++yCtr, --yDiff, yp += 8) { + for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) { + v = map.mazeLookup(Common::Point(xDiff, yDiff), 4); + int wallType = map.mazeDataCurrent()._wallTypes[v]; + + if (wallType && map._currentSteppedOn) + map._tileSprites.draw(screen, wallType, Common::Point(xp, yp)); + } + } + + for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16; + ++yCtr, --yDiff, yp += 8) { + for (int xCtr = 0, xp = 80, xDiff = xDiffStart + 1; xp < 240; + ++xCtr, ++xDiff, xp += 10) { + if (xCtr == (arrowPt.x / 10) && yCtr == (14 - (arrowPt.y)) && frameEndFlag) + map._tileSprites.draw(screen, party._mazeDirection + 1, + Common::Point(arrowPt.x + 81, arrowPt.y + 29)); + + v = map.mazeLookup(Common::Point(xDiff, yDiff), 12); + int frame; + switch (v) { + case SURFTYPE_WATER: + frame = 18; + break; + case SURFTYPE_DIRT: + frame = 34; + break; + case SURFTYPE_GRASS: + frame = 22; + break; + case SURFTYPE_SNOW: + case SURFTYPE_SEWER: + frame = 16; + break; + case SURFTYPE_SWAMP: + case SURFTYPE_ROAD: + frame = 2; + case SURFTYPE_LAVA: + frame = 30; + break; + case SURFTYPE_DESERT: + frame = 32; + break; + case SURFTYPE_DWATER: + frame = 20; + break; + case SURFTYPE_TFLR: + frame = 28; + break; + case SURFTYPE_SKY: + frame = 14; + break; + case SURFTYPE_CROAD: + frame = frame2 + 4; + break; + case SURFTYPE_CLOUD: + frame = 24; + break; + case SURFTYPE_SCORCH: + frame = 26; + break; + default: + frame = -1; + break; + } + + if (frame != -1 && map._currentSteppedOn) + map._tileSprites.draw(screen, frame, Common::Point(xp, yp)); + + v = map.mazeLookup(Common::Point(xDiff, yDiff), 0); + switch (v) { + case SURFTYPE_WATER: + frame = 19; + break; + case SURFTYPE_DIRT: + frame = 35; + break; + case SURFTYPE_GRASS: + frame = 23; + break; + case SURFTYPE_SNOW: + case SURFTYPE_SEWER: + frame = 17; + break; + case SURFTYPE_SWAMP: + case SURFTYPE_ROAD: + frame = 3; + break; + case SURFTYPE_LAVA: + frame = 31; + break; + case SURFTYPE_DESERT: + frame = 33; + break; + case SURFTYPE_DWATER: + frame = 21; + break; + case SURFTYPE_TFLR: + frame = 29; + break; + case SURFTYPE_SKY: + frame = 15; + break; + case SURFTYPE_CROAD: + frame = frame2 + 5; + break; + case SURFTYPE_CLOUD: + frame = 25; + break; + case SURFTYPE_SCORCH: + frame = 27; + break; + default: + frame = -1; + break; + } + + if (frame != -1 && map._currentSteppedOn) + map._tileSprites.draw(screen, frame, Common::Point(xp, yp)); + } + } + + for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16; + ++yCtr, --yDiff, yp += 8) { + for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) { + v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff); + + if (v != INVALID_CELL && map._currentSteppedOn) + map._tileSprites.draw(screen, 1, Common::Point(xp, yp)); + } + } + } else { + // Draw indoors map + frame2 = (frame2 + 2) % 8; + + for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16; + ++yCtr, --yDiff, yp += 8) { + for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) { + v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff); + + if (v != INVALID_CELL && map._currentSteppedOn) + map._tileSprites.draw(screen, 0, Common::Point(xp, yp)); + } + } + + for (int yDiff = yDiffStart - 1, yp = 38; yp < 171; --yDiff, yp += 8) { + v = map.mazeLookup(Common::Point(pt.x - 8, yDiff), 0, 0xffff); + + if (v != INVALID_CELL && map._currentSurfaceId != 0 && map._currentSteppedOn) + map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[v], + Common::Point(75, yp)); + } + + v = map.mazeLookup(Common::Point(pt.x - 8, pt.y + 8), 0, 0xffff); + if (v != INVALID_CELL && map._currentSurfaceId != 0 && map._currentSteppedOn) + map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[v], + Common::Point(75, 35)); + + for (int xp = 85, xDiff = xDiffStart + 1; xp < 245; xp += 10, ++xDiff) { + v = map.mazeLookup(Common::Point(xDiff, pt.y + 8), 0, 0xffff); + + if (v != INVALID_CELL && map._currentSurfaceId != 0 && map._currentSteppedOn) + map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[v], + Common::Point(xp, 35)); + } + + for (int xp = 80, yp = 158, xDiff = pt.x - 7, yDiff = pt.y - 8; xp < 250; + xp += 10, yp += 8, ++xDiff, ++yDiff) { + v = map.mazeLookup(Common::Point(pt.x - 8, yDiff), 12); + + int frame; + switch (v) { + case SURFTYPE_WATER: + frame = 18; + break; + case SURFTYPE_GRASS: + frame = 24; + break; + case SURFTYPE_SNOW: + case SURFTYPE_SEWER: + frame = 16; + break; + case SURFTYPE_SWAMP: + case SURFTYPE_ROAD: + frame = 2; + break; + case SURFTYPE_LAVA: + frame = 30; + break; + case SURFTYPE_DESERT: + frame = 32; + break; + case SURFTYPE_DWATER: + frame = 20; + break; + case SURFTYPE_TFLR: + frame = 28; + break; + case SURFTYPE_SKY: + frame = 14; + break; + case SURFTYPE_CROAD: + frame = frame2 + 4; + break; + case SURFTYPE_CLOUD: + frame = 24; + break; + case SURFTYPE_SCORCH: + frame = 26; + break; + default: + frame = -1; + break; + } + + if (frame != -1 && map._currentSteppedOn) + map._tileSprites.draw(screen, frame, Common::Point(70, yp)); + + v = map.mazeLookup(Common::Point(xDiff, pt.y + 8), 0); + + switch (v) { + case SURFTYPE_WATER: + frame = 19; + break; + case SURFTYPE_DIRT: + frame = 35; + break; + case SURFTYPE_GRASS: + frame = 23; + break; + case SURFTYPE_SNOW: + case SURFTYPE_SEWER: + frame = 17; + break; + case SURFTYPE_SWAMP: + case SURFTYPE_ROAD: + frame = 3; + break; + case SURFTYPE_LAVA: + frame = 31; + break; + case SURFTYPE_DESERT: + frame = 33; + break; + case SURFTYPE_DWATER: + frame = 21; + break; + case SURFTYPE_TFLR: + frame = 29; + break; + case SURFTYPE_SKY: + frame = 15; + break; + case SURFTYPE_CROAD: + frame = frame2 + 5; + break; + case SURFTYPE_CLOUD: + frame = 25; + break; + case SURFTYPE_SCORCH: + frame = 27; + break; + default: + frame = -1; + break; + } + + if (frame != -1 && map._currentSteppedOn) + map._tileSprites.draw(screen, frame, Common::Point(xp, 30)); + } + + for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16; + ++yCtr, --yDiff, yp += 8) { + for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) { + v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff); + + if (v != INVALID_CELL && map._currentSteppedOn) + map._tileSprites.draw(screen, 0, Common::Point(xp, yp)); + } + } + } + + screen._windows[5].frame(); + if (!map._isOutdoors) { + map._tileSprites.draw(screen, 52, Common::Point(76, 30)); + } else if (frameEndFlag) { + globalSprites.draw(screen, party._mazeDirection + 1, + Common::Point(arrowPt.x + 76, arrowPt.y + 25)); + } + + if (events.timeElapsed() > 5) { + // Set the flag to make the basic arrow blinking effect + frameEndFlag = true; + events.updateGameCounter(); + } + + screen._windows[5].writeString(Common::String::format(MAP_TEXT, + map._mazeName.c_str(), party._mazePosition.x, + party._mazePosition.y, DIRECTION_TEXT[party._mazeDirection])); + screen._windows[5].update(); + screen._windows[3].update(); + + events.pollEvents(); + } while (!_vm->shouldQuit() && !events.isKeyMousePressed()); + + events.clearEvents(); + screen._windows[5].close(); +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_automap.h b/engines/xeen/dialogs_automap.h new file mode 100644 index 0000000000..f20f9b0104 --- /dev/null +++ b/engines/xeen/dialogs_automap.h @@ -0,0 +1,45 @@ +/* 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 XEEN_DIALOGS_AUTOMAP_H +#define XEEN_DIALOGS_AUTOMAP_H + +#include "xeen/dialogs.h" + +namespace Xeen { + +class XeenEngine; + +class AutoMapDialog: public ButtonContainer { +private: + XeenEngine *_vm; + + AutoMapDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + void execute(); +public: + static void show(XeenEngine *vm); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_AUTOMAP_H */ diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index ece8ff3054..d3fe234017 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -22,6 +22,7 @@ #include "xeen/interface.h" #include "xeen/dialogs_error.h" +#include "xeen/dialogs_automap.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -672,6 +673,12 @@ void Interface::perform() { // Toggle minimap party._automapOn = !party._automapOn; break; + + case Common::KEYCODE_m: + // Show map dialog + AutoMapDialog::show(_vm); + break; + default: break; } diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index dcae6cc406..46f52729e7 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -4580,7 +4580,7 @@ void InterfaceMap::assembleBorder() { // Draw direction character if direction sense is active if (_vm->_party->checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) { - const char *dirText = DIRECTION_TEXT[_vm->_party->_mazeDirection]; + const char *dirText = DIRECTION_TEXT_UPPER[_vm->_party->_mazeDirection]; Common::String msg = Common::String::format( "\002""08\003""c\013""139\011""116%c\014""d\001", *dirText); screen._windows[0].writeString(msg); diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 7d268efb8e..abc36411ee 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -347,7 +347,6 @@ class Map { private: XeenEngine *_vm; MazeData _mazeData[9]; - Common::String _mazeName; SpriteResource _wallPicSprites; int _sideTownPortal; int _sidePictures; @@ -357,6 +356,7 @@ private: void loadEvents(int mapId); public: + Common::String _mazeName; bool _isOutdoors; MonsterObjectData _mobData; MonsterData _monsterData; diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index be951239d3..50a8947afa 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -8,6 +8,8 @@ MODULE_OBJS := \ debugger.o \ detection.o \ dialogs.o \ + automap.o \ + dialogs_automap.o \ dialogs_confirm.o \ dialogs_error.o \ dialogs_options.o \ diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index ed304dc9e1..05eff2d580 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -271,7 +271,9 @@ const byte TEXT_COLORS[40][4] = { { 0x00, 0xDB, 0xDB, 0xDB }, }; -const char *const DIRECTION_TEXT[4] = { "NORTH", "EAST", "SOUTH", "WEST" }; +const char *const DIRECTION_TEXT_UPPER[4] = { "NORTH", "EAST", "SOUTH", "WEST" }; + +const char *const DIRECTION_TEXT[4] = { "North", "East", "South", "West" }; const char *const RACE_NAMES[5] = { "Human", "Elf", "Dwarf", "Gnome", "H-Orc" }; @@ -815,15 +817,19 @@ const char *const SPELLS_PURCHASE = "\xC""09%s\xC""d for %u?"; const char *const SPELL_DETAILS = -"\xD\x2\x3""c\xB""122\x9""013\xC""37C\xC""dast" -"\x9""040\xC""37N\xC""dew\x9""067ESC\x1""000\xB""000\x3""cCast Spell\n" -"\n" -"%s\x3l\n" -"\n" -"Spell Ready:\x3""c\n" -"\n" -"\xC""09%s\xC""d\x2\x3l\n" -"\xB""082Cost\x3r\x9""000%u/%u\x3l\n" -"Cur SP\x3r\x9""000%u\x1"; + "\xD\x2\x3""c\xB""122\x9""013\xC""37C\xC""dast" + "\x9""040\xC""37N\xC""dew\x9""067ESC\x1""000\xB""000\x3""cCast Spell\n" + "\n" + "%s\x3l\n" + "\n" + "Spell Ready:\x3""c\n" + "\n" + "\xC""09%s\xC""d\x2\x3l\n" + "\xB""082Cost\x3r\x9""000%u/%u\x3l\n" + "Cur SP\x3r\x9""000%u\x1"; + +const char *const MAP_TEXT = + "\x3""c\xB""000\x9""000%s\x3l\xB""139" + "\x9""000X = %d\x3r\x9""000Y = %d\x3""c\x9""000%s"; } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 37afb2cc76..70fdcf65b1 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -56,6 +56,8 @@ extern const byte SYMBOLS[20][64]; extern const byte TEXT_COLORS[40][4]; +extern const char *const DIRECTION_TEXT_UPPER[4]; + extern const char *const DIRECTION_TEXT[4]; extern const char *const RACE_NAMES[5]; @@ -244,6 +246,8 @@ extern const char *const SPELLS_PURCHASE; extern const char *const SPELL_DETAILS; +extern const char *const MAP_TEXT; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From b22418de083e8eee1eb88e83a3b3acec6956d74b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 31 Jan 2015 12:17:15 -0500 Subject: XEEN: Bugfixes for the automap dialog --- engines/xeen/dialogs_automap.cpp | 369 ++++++++++++++++++++------------------- 1 file changed, 191 insertions(+), 178 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_automap.cpp b/engines/xeen/dialogs_automap.cpp index 08cf593f7b..da75f5e20b 100644 --- a/engines/xeen/dialogs_automap.cpp +++ b/engines/xeen/dialogs_automap.cpp @@ -41,10 +41,8 @@ void AutoMapDialog::execute() { Party &party = *_vm->_party; int frame2 = intf._overallFrame * 2; int varSI = 1; - bool frameEndFlag; + bool frameEndFlag = false; - int yDiffStart = 8; - int xDiffStart = 248; Common::Point pt = party._mazePosition; Common::Point arrowPt; SpriteResource globalSprites; @@ -82,15 +80,14 @@ void AutoMapDialog::execute() { events.updateGameCounter(); do { - if (drawFlag) - intf.draw3d(false); +// if (drawFlag) +// intf.draw3d(false); screen._windows[5].writeString("\n"); if (map._isOutdoors) { // Draw outdoors map - for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16; - ++yCtr, --yDiff, yp += 8) { - for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) { + for (int yp = 38, yDiff = pt.y + 7; pt.y < 166; --yDiff, yp += 8) { + for (int xp = 80, xDiff = pt.x - 7; xp < 240; xp += 10, ++xDiff) { v = map.mazeLookup(Common::Point(xDiff, yDiff), 0); if (map._currentSteppedOn) { @@ -100,9 +97,8 @@ void AutoMapDialog::execute() { } } - for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16; - ++yCtr, --yDiff, yp += 8) { - for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) { + for (int yp = 38, yDiff = pt.y + 7; yp < 166; --yDiff, yp += 8) { + for (int xp = 80, xDiff = pt.x - 7; xp < 240; xp += 10, ++xDiff) { v = map.mazeLookup(Common::Point(xDiff, yDiff), 4); int wallType = map.mazeDataCurrent()._wallTypes[v]; @@ -111,124 +107,12 @@ void AutoMapDialog::execute() { } } - for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16; - ++yCtr, --yDiff, yp += 8) { - for (int xCtr = 0, xp = 80, xDiff = xDiffStart + 1; xp < 240; - ++xCtr, ++xDiff, xp += 10) { - if (xCtr == (arrowPt.x / 10) && yCtr == (14 - (arrowPt.y)) && frameEndFlag) - map._tileSprites.draw(screen, party._mazeDirection + 1, - Common::Point(arrowPt.x + 81, arrowPt.y + 29)); - - v = map.mazeLookup(Common::Point(xDiff, yDiff), 12); - int frame; - switch (v) { - case SURFTYPE_WATER: - frame = 18; - break; - case SURFTYPE_DIRT: - frame = 34; - break; - case SURFTYPE_GRASS: - frame = 22; - break; - case SURFTYPE_SNOW: - case SURFTYPE_SEWER: - frame = 16; - break; - case SURFTYPE_SWAMP: - case SURFTYPE_ROAD: - frame = 2; - case SURFTYPE_LAVA: - frame = 30; - break; - case SURFTYPE_DESERT: - frame = 32; - break; - case SURFTYPE_DWATER: - frame = 20; - break; - case SURFTYPE_TFLR: - frame = 28; - break; - case SURFTYPE_SKY: - frame = 14; - break; - case SURFTYPE_CROAD: - frame = frame2 + 4; - break; - case SURFTYPE_CLOUD: - frame = 24; - break; - case SURFTYPE_SCORCH: - frame = 26; - break; - default: - frame = -1; - break; - } - - if (frame != -1 && map._currentSteppedOn) - map._tileSprites.draw(screen, frame, Common::Point(xp, yp)); - - v = map.mazeLookup(Common::Point(xDiff, yDiff), 0); - switch (v) { - case SURFTYPE_WATER: - frame = 19; - break; - case SURFTYPE_DIRT: - frame = 35; - break; - case SURFTYPE_GRASS: - frame = 23; - break; - case SURFTYPE_SNOW: - case SURFTYPE_SEWER: - frame = 17; - break; - case SURFTYPE_SWAMP: - case SURFTYPE_ROAD: - frame = 3; - break; - case SURFTYPE_LAVA: - frame = 31; - break; - case SURFTYPE_DESERT: - frame = 33; - break; - case SURFTYPE_DWATER: - frame = 21; - break; - case SURFTYPE_TFLR: - frame = 29; - break; - case SURFTYPE_SKY: - frame = 15; - break; - case SURFTYPE_CROAD: - frame = frame2 + 5; - break; - case SURFTYPE_CLOUD: - frame = 25; - break; - case SURFTYPE_SCORCH: - frame = 27; - break; - default: - frame = -1; - break; - } - - if (frame != -1 && map._currentSteppedOn) - map._tileSprites.draw(screen, frame, Common::Point(xp, yp)); - } - } + + for (int yp = 38, yDiff = pt.y + 7; yp < 166; yp += 8, --yDiff) { + for (int xp = 80, xDiff = -7; xp < 240; xp += 10, ++xDiff) { + v = map.mazeLookup(Common::Point(xDiff, yDiff), 8); - for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16; - ++yCtr, --yDiff, yp += 8) { - for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) { - v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff); - - if (v != INVALID_CELL && map._currentSteppedOn) + if (v && map._currentSteppedOn) map._tileSprites.draw(screen, 1, Common::Point(xp, yp)); } } @@ -236,79 +120,94 @@ void AutoMapDialog::execute() { // Draw indoors map frame2 = (frame2 + 2) % 8; - for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16; - ++yCtr, --yDiff, yp += 8) { - for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) { + // Draw ground tiles + for (int yp = 38, yDiff = pt.y + 7; yp < 166; yp += 8, --yDiff) { + for (int xp = 80, xDiff = pt.x - 7; xp < 240; xp += 10, ++xDiff) { v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff); if (v != INVALID_CELL && map._currentSteppedOn) map._tileSprites.draw(screen, 0, Common::Point(xp, yp)); } } - - for (int yDiff = yDiffStart - 1, yp = 38; yp < 171; --yDiff, yp += 8) { + + // Draw thinner ground tiles on the left edge of the map + for (int yp = 43, yDiff = pt.y + 7; yp < 171; yp += 8, --yDiff) { v = map.mazeLookup(Common::Point(pt.x - 8, yDiff), 0, 0xffff); if (v != INVALID_CELL && map._currentSurfaceId != 0 && map._currentSteppedOn) - map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[v], - Common::Point(75, yp)); + map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[ + map._currentSurfaceId], Common::Point(75, yp)); } - + + // Draw thin tile portion on top-left corner of map v = map.mazeLookup(Common::Point(pt.x - 8, pt.y + 8), 0, 0xffff); if (v != INVALID_CELL && map._currentSurfaceId != 0 && map._currentSteppedOn) - map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[v], - Common::Point(75, 35)); - - for (int xp = 85, xDiff = xDiffStart + 1; xp < 245; xp += 10, ++xDiff) { + map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[ + map._currentSurfaceId], Common::Point(75, 35)); + + // Draw any thin tiles at the very top of the map + for (int xp = 85, xDiff = pt.x - 7; xp < 245; xp += 10, ++xDiff) { v = map.mazeLookup(Common::Point(xDiff, pt.y + 8), 0, 0xffff); if (v != INVALID_CELL && map._currentSurfaceId != 0 && map._currentSteppedOn) - map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[v], - Common::Point(xp, 35)); + map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[ + map._currentSurfaceId], Common::Point(xp, 35)); + } + + // Draw the default ground tiles + for (int yp = 43, yDiff = pt.y + 7; yp < 171; yp += 8, --yDiff) { + for (int xp = 85, xDiff = pt.x - 7; xp < 245; xp += 10, ++xDiff) { + v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff); + + if (v != INVALID_CELL && map._currentSteppedOn) + map._tileSprites.draw(screen, 0, Common::Point(xp, yp)); + } } + // Draw walls on left and top edges of map for (int xp = 80, yp = 158, xDiff = pt.x - 7, yDiff = pt.y - 8; xp < 250; - xp += 10, yp += 8, ++xDiff, ++yDiff) { + xp += 10, yp -= 8, ++xDiff, ++yDiff) { + // Draw walls on left edge of map v = map.mazeLookup(Common::Point(pt.x - 8, yDiff), 12); int frame; switch (v) { - case SURFTYPE_WATER: + case SURFTYPE_DIRT: frame = 18; break; - case SURFTYPE_GRASS: - frame = 24; - break; case SURFTYPE_SNOW: - case SURFTYPE_SEWER: - frame = 16; + frame = 22; break; case SURFTYPE_SWAMP: - case SURFTYPE_ROAD: - frame = 2; + case SURFTYPE_CLOUD: + frame = 16; break; case SURFTYPE_LAVA: - frame = 30; + case SURFTYPE_DWATER: + frame = 2; break; case SURFTYPE_DESERT: + frame = 30; + break; + case SURFTYPE_ROAD: frame = 32; break; - case SURFTYPE_DWATER: + case SURFTYPE_TFLR: frame = 20; break; - case SURFTYPE_TFLR: + case SURFTYPE_SKY: frame = 28; break; - case SURFTYPE_SKY: + case SURFTYPE_CROAD: frame = 14; break; - case SURFTYPE_CROAD: + case SURFTYPE_SEWER: frame = frame2 + 4; break; - case SURFTYPE_CLOUD: + case SURFTYPE_SCORCH: frame = 24; break; - case SURFTYPE_SCORCH: + case SURFTYPE_SPACE: frame = 26; break; default: @@ -319,48 +218,49 @@ void AutoMapDialog::execute() { if (frame != -1 && map._currentSteppedOn) map._tileSprites.draw(screen, frame, Common::Point(70, yp)); + // Draw walls on top edge of map v = map.mazeLookup(Common::Point(xDiff, pt.y + 8), 0); switch (v) { - case SURFTYPE_WATER: + case SURFTYPE_DIRT: frame = 19; break; - case SURFTYPE_DIRT: + case SURFTYPE_GRASS: frame = 35; break; - case SURFTYPE_GRASS: + case SURFTYPE_SNOW: frame = 23; break; - case SURFTYPE_SNOW: - case SURFTYPE_SEWER: + case SURFTYPE_SWAMP: + case SURFTYPE_CLOUD: frame = 17; break; - case SURFTYPE_SWAMP: - case SURFTYPE_ROAD: + case SURFTYPE_LAVA: + case SURFTYPE_DWATER: frame = 3; break; - case SURFTYPE_LAVA: + case SURFTYPE_DESERT: frame = 31; break; - case SURFTYPE_DESERT: + case SURFTYPE_ROAD: frame = 33; break; - case SURFTYPE_DWATER: + case SURFTYPE_TFLR: frame = 21; break; - case SURFTYPE_TFLR: + case SURFTYPE_SKY: frame = 29; break; - case SURFTYPE_SKY: + case SURFTYPE_CROAD: frame = 15; break; - case SURFTYPE_CROAD: + case SURFTYPE_SEWER: frame = frame2 + 5; break; - case SURFTYPE_CLOUD: + case SURFTYPE_SCORCH: frame = 25; break; - case SURFTYPE_SCORCH: + case SURFTYPE_SPACE: frame = 27; break; default: @@ -372,12 +272,125 @@ void AutoMapDialog::execute() { map._tileSprites.draw(screen, frame, Common::Point(xp, 30)); } - for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16; - ++yCtr, --yDiff, yp += 8) { - for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) { + for (int yCtr = 0, yp = 38, yDiff = pt.y + 7; yCtr < 16; ++yCtr, yp += 8, --yDiff) { + for (int xCtr = 0, xp = 80, xDiff = pt.x - 7; xCtr < 16; ++xCtr, xp += 10, ++xDiff) { + // Draw the arrow if at the correct position + if ((arrowPt.x / 10) == xCtr && (14 - (arrowPt.y / 10)) == yCtr && frameEndFlag) { + globalSprites.draw(screen, party._mazeDirection + 1, + Common::Point(arrowPt.x, arrowPt.y + 29)); + } + + v = map.mazeLookup(Common::Point(xDiff, yDiff), 12); + int frame; + switch (v) { + case SURFTYPE_DIRT: + frame = 18; + break; + case SURFTYPE_GRASS: + frame = 34; + break; + case SURFTYPE_SNOW: + frame = 22; + break; + case SURFTYPE_SWAMP: + case SURFTYPE_CLOUD: + frame = 16; + break; + case SURFTYPE_LAVA: + case SURFTYPE_DWATER: + frame = 2; + break; + case SURFTYPE_DESERT: + frame = 30; + break; + case SURFTYPE_ROAD: + frame = 32; + break; + case SURFTYPE_TFLR: + frame = 20; + break; + case SURFTYPE_SKY: + frame = 28; + break; + case SURFTYPE_CROAD: + frame = 14; + break; + case SURFTYPE_SEWER: + frame = frame2 + 4; + break; + case SURFTYPE_SCORCH: + frame = 24; + break; + case SURFTYPE_SPACE: + frame = 26; + break; + default: + frame = -1; + break; + } + + if (frame != -1 && map._currentSteppedOn) + map._tileSprites.draw(screen, frame, Common::Point(xp, yp)); + + v = map.mazeLookup(Common::Point(xDiff, yDiff), 0); + switch (v) { + case SURFTYPE_DIRT: + frame = 19; + break; + case SURFTYPE_GRASS: + frame = 35; + break; + case SURFTYPE_SNOW: + frame = 23; + break; + case SURFTYPE_SWAMP: + case SURFTYPE_CLOUD: + frame = 17; + break; + case SURFTYPE_LAVA: + case SURFTYPE_DWATER: + frame = 3; + break; + case SURFTYPE_DESERT: + frame = 31; + break; + case SURFTYPE_ROAD: + frame = 33; + break; + case SURFTYPE_TFLR: + frame = 21; + break; + case SURFTYPE_SKY: + frame = 29; + break; + case SURFTYPE_CROAD: + frame = 15; + break; + case SURFTYPE_SEWER: + frame = frame2 + 5; + break; + case SURFTYPE_SCORCH: + frame = 25; + break; + case SURFTYPE_SPACE: + frame = 27; + break; + default: + frame = -1; + break; + } + + if (frame != -1 && map._currentSteppedOn) + map._tileSprites.draw(screen, frame, Common::Point(xp, yp)); + } + } + + // Draw overlay on cells that haven't been stepped on yet + for (int yDiff = pt.y + 7, yp = 38; yp < 166; --yDiff, yp += 8) { + for (int xp = 80, xDiff = pt.x - 7; xp < 240; xp += 10, ++xDiff) { v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff); - if (v != INVALID_CELL && map._currentSteppedOn) + if (v != INVALID_CELL && !map._currentSteppedOn) map._tileSprites.draw(screen, 0, Common::Point(xp, yp)); } } @@ -393,7 +406,7 @@ void AutoMapDialog::execute() { if (events.timeElapsed() > 5) { // Set the flag to make the basic arrow blinking effect - frameEndFlag = true; + frameEndFlag = !frameEndFlag; events.updateGameCounter(); } -- cgit v1.2.3 From d67b8d364d8c2a48d26fd0349cc902786b50235b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 31 Jan 2015 15:28:53 -0500 Subject: XEEN: More automap dialog fixes --- engines/xeen/dialogs_automap.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_automap.cpp b/engines/xeen/dialogs_automap.cpp index da75f5e20b..539911058a 100644 --- a/engines/xeen/dialogs_automap.cpp +++ b/engines/xeen/dialogs_automap.cpp @@ -80,8 +80,8 @@ void AutoMapDialog::execute() { events.updateGameCounter(); do { -// if (drawFlag) -// intf.draw3d(false); + if (drawFlag) + intf.draw3d(false); screen._windows[5].writeString("\n"); if (map._isOutdoors) { @@ -277,7 +277,7 @@ void AutoMapDialog::execute() { // Draw the arrow if at the correct position if ((arrowPt.x / 10) == xCtr && (14 - (arrowPt.y / 10)) == yCtr && frameEndFlag) { globalSprites.draw(screen, party._mazeDirection + 1, - Common::Point(arrowPt.x, arrowPt.y + 29)); + Common::Point(arrowPt.x + 81, arrowPt.y + 29)); } v = map.mazeLookup(Common::Point(xDiff, yDiff), 12); @@ -384,14 +384,14 @@ void AutoMapDialog::execute() { map._tileSprites.draw(screen, frame, Common::Point(xp, yp)); } } - + // Draw overlay on cells that haven't been stepped on yet for (int yDiff = pt.y + 7, yp = 38; yp < 166; --yDiff, yp += 8) { for (int xp = 80, xDiff = pt.x - 7; xp < 240; xp += 10, ++xDiff) { v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff); - if (v != INVALID_CELL && !map._currentSteppedOn) - map._tileSprites.draw(screen, 0, Common::Point(xp, yp)); + if (v == INVALID_CELL || !map._currentSteppedOn) + map._tileSprites.draw(screen, 1, Common::Point(xp, yp)); } } } @@ -417,6 +417,7 @@ void AutoMapDialog::execute() { screen._windows[3].update(); events.pollEvents(); + drawFlag = false; } while (!_vm->shouldQuit() && !events.isKeyMousePressed()); events.clearEvents(); -- cgit v1.2.3 From 73a522150f5097e83f9ea24974265fcb1c827a99 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 31 Jan 2015 15:51:20 -0500 Subject: XEEN: Yet more bugfixes for automap dialog --- engines/xeen/dialogs_automap.cpp | 8 +++++--- engines/xeen/interface_map.cpp | 8 +++++++- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_automap.cpp b/engines/xeen/dialogs_automap.cpp index 539911058a..61821425dd 100644 --- a/engines/xeen/dialogs_automap.cpp +++ b/engines/xeen/dialogs_automap.cpp @@ -120,7 +120,7 @@ void AutoMapDialog::execute() { // Draw indoors map frame2 = (frame2 + 2) % 8; - // Draw ground tiles + // Draw default ground for all the valid explored areas for (int yp = 38, yDiff = pt.y + 7; yp < 166; yp += 8, --yDiff) { for (int xp = 80, xDiff = pt.x - 7; xp < 240; xp += 10, ++xDiff) { v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff); @@ -159,8 +159,9 @@ void AutoMapDialog::execute() { for (int xp = 85, xDiff = pt.x - 7; xp < 245; xp += 10, ++xDiff) { v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff); - if (v != INVALID_CELL && map._currentSteppedOn) - map._tileSprites.draw(screen, 0, Common::Point(xp, yp)); + if (v != INVALID_CELL && map._currentSurfaceId && map._currentSteppedOn) + map._tileSprites.draw(screen, map.mazeData()._surfaceTypes[ + map._currentSurfaceId], Common::Point(xp, yp)); } } @@ -272,6 +273,7 @@ void AutoMapDialog::execute() { map._tileSprites.draw(screen, frame, Common::Point(xp, 30)); } + // Draw any walls on the cells for (int yCtr = 0, yp = 38, yDiff = pt.y + 7; yCtr < 16; ++yCtr, yp += 8, --yDiff) { for (int xCtr = 0, xp = 80, xDiff = pt.x - 7; xCtr < 16; ++xCtr, xp += 10, ++xDiff) { // Draw the arrow if at the correct position diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 46f52729e7..84f8fa6aa1 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -756,7 +756,13 @@ void InterfaceMap::draw3d(bool updateFlag) { if (_vm->_mode == MODE_9) { // TODO } - events.wait(2); + + // TODO: Check use of updateFlag here. Original doesn't have it, but I + // wanted to ensure in places like the AutoMapDialog, that the draw3d + // doesn't result in the screen updating until the dialog has had + // a chance to full render itself + if (updateFlag) + events.wait(2); } /** -- cgit v1.2.3 From 40b2f886c374129bcb275400d1228752f20154da Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 31 Jan 2015 17:39:52 -0500 Subject: XEEN: Implement the Info dialog --- engines/xeen/dialogs_info.cpp | 128 ++++++++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_info.h | 47 ++++++++++++++++ engines/xeen/interface.cpp | 6 ++ engines/xeen/module.mk | 1 + engines/xeen/resources.cpp | 34 +++++++++++ engines/xeen/resources.h | 28 +++++++++ 6 files changed, 244 insertions(+) create mode 100644 engines/xeen/dialogs_info.cpp create mode 100644 engines/xeen/dialogs_info.h (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_info.cpp b/engines/xeen/dialogs_info.cpp new file mode 100644 index 0000000000..7ccaa7fe71 --- /dev/null +++ b/engines/xeen/dialogs_info.cpp @@ -0,0 +1,128 @@ +/* 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 "xeen/dialogs_info.h" +#include "xeen/resources.h" +#include "xeen/xeen.h" + +namespace Xeen { + +void InfoDialog::show(XeenEngine *vm) { + InfoDialog *dlg = new InfoDialog(vm); + dlg->execute(); + delete dlg; +} + +void InfoDialog::execute() { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + + protectionText(); + Common::String statusText = ""; + for (uint idx = 0; idx < _lines.size(); ++idx) + statusText += _lines[idx]; + + Common::String gameName; + if (_vm->getGameID() == GType_Swords) + gameName = SWORDS_GAME_TEXT; + else if (_vm->getGameID() == GType_Clouds) + gameName = CLOUDS_GAME_TEXT; + else if (_vm->getGameID() == GType_DarkSide) + gameName = DARKSIDE_GAME_TEXT; + else + gameName = WORLD_GAME_TEXT; + + // Form the display message + int hour = party._minutes / 60; + Common::String details = Common::String::format(GAME_INFORMATION, + gameName.c_str(), WEEK_DAY_STRINGS[party._day % 10], + (hour > 12) ? hour - 12 : (!hour ? 12 : hour), + party._minutes % 60, (hour > 11) ? 'p' : 'a', + party._day, party._year, statusText.c_str()); + + Window &w = screen._windows[28]; + w.setBounds(Common::Rect(88, 20, 248, 112)); + w.open(); + + do { + events.updateGameCounter(); + intf.draw3d(false); + w.frame(); + w.writeString(details); + w.update(); + + events.wait(1, true); + } while (!_vm->shouldQuit() && !events.isKeyMousePressed()); + + events.clearEvents(); + w.close(); +} + +void InfoDialog::protectionText() { + Party &party = *_vm->_party; + Common::StringArray _lines; + const char *const AA_L024 = "\x3l\n\x9""024"; + const char *const AA_R124 = "\x3r\x9""124"; + + if (party._lightCount) { + _lines.push_back(Common::String::format(LIGHT_COUNT_TEXT, party._lightCount)); + } + + if (party._fireResistence) { + _lines.push_back(Common::String::format(FIRE_RESISTENCE_TEXT, + _lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._fireResistence)); + } + + if (party._electricityResistence) { + _lines.push_back(Common::String::format(ELECRICITY_RESISTENCE_TEXT, + _lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._electricityResistence)); + } + + if (party._coldResistence) { + _lines.push_back(Common::String::format(COLD_RESISTENCE_TEXT, + _lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._coldResistence)); + } + + if (party._poisonResistence) { + _lines.push_back(Common::String::format(POISON_RESISTENCE_TEXT, + _lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._poisonResistence)); + } + + if (party._clairvoyanceActive) { + _lines.push_back(Common::String::format(CLAIRVOYANCE_TEXT, + _lines.size() == 0 ? 10 : 1, AA_L024, AA_R124)); + } + + if (party._levitateActive) { + _lines.push_back(Common::String::format(LEVITATE_TEXT, + _lines.size() == 0 ? 10 : 1, AA_L024, AA_R124)); + } + + if (party._walkOnWaterActive) { + _lines.push_back(Common::String::format(WALK_ON_WATER_TEXT, + _lines.size() == 0 ? 10 : 1, AA_L024, AA_R124)); + } +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_info.h b/engines/xeen/dialogs_info.h new file mode 100644 index 0000000000..66b915788b --- /dev/null +++ b/engines/xeen/dialogs_info.h @@ -0,0 +1,47 @@ +/* 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 XEEN_DIALOGS_INFO_H +#define XEEN_DIALOGS_INFO_H + +#include "common/str-array.h" +#include "xeen/dialogs.h" + +namespace Xeen { + +class InfoDialog : public ButtonContainer { +private: + XeenEngine *_vm; + Common::StringArray _lines; + + InfoDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + void execute(); + + void protectionText(); +public: + static void show(XeenEngine *vm); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_INFO_H */ diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index d3fe234017..3e958b391c 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -23,6 +23,7 @@ #include "xeen/interface.h" #include "xeen/dialogs_error.h" #include "xeen/dialogs_automap.h" +#include "xeen/dialogs_info.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -674,6 +675,11 @@ void Interface::perform() { party._automapOn = !party._automapOn; break; + case Common::KEYCODE_i: + // Show Info dialog + InfoDialog::show(_vm); + break; + case Common::KEYCODE_m: // Show map dialog AutoMapDialog::show(_vm); diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 50a8947afa..4bb8bd99c0 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -13,6 +13,7 @@ MODULE_OBJS := \ dialogs_confirm.o \ dialogs_error.o \ dialogs_options.o \ + dialogs_info.o \ dialogs_input.o \ dialogs_spells.o \ dialogs_whowill.o \ diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 05eff2d580..dafe321ab5 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -832,4 +832,38 @@ const char *const MAP_TEXT = "\x3""c\xB""000\x9""000%s\x3l\xB""139" "\x9""000X = %d\x3r\x9""000Y = %d\x3""c\x9""000%s"; +const char *const LIGHT_COUNT_TEXT = "\x3l\n\n\t024Light\x3r\t124%d"; + +const char *const FIRE_RESISTENCE_TEXT = "%c%sFire%s%u"; + +const char *const ELECRICITY_RESISTENCE_TEXT = "%c%sElectricity%s%u"; + +const char *const COLD_RESISTENCE_TEXT = "c%sCold%s%u"; + +const char *const POISON_RESISTENCE_TEXT = "%c%sPoison/Acid%s%u"; + +const char *const CLAIRVOYANCE_TEXT = "%c%sClairvoyance%s"; + +const char *const LEVITATE_TEXT = "%c%sLevitate%s"; + +const char *const WALK_ON_WATER_TEXT = "%c%sWalk on Water"; + +const char *const GAME_INFORMATION = + "\xD\x3""c\x9""000\xB""001\xC""37%s of Xeen\xC""d\n" + "Game Information\n" + "\n" + "Today is \xC""37%ssday\xC""d\n" + "\n" + "\x9""032Time\x9""072Day\x9""112Year\n" + "\x9""032\xC""37%d:%02d%c\x9""072%u\x9""112%u\xC""d%s"; + +const char *const WORLD_GAME_TEXT = "World"; +const char *const DARKSIDE_GAME_TEXT = "Darkside"; +const char *const CLOUDS_GAME_TEXT = "Clouds"; +const char *const SWORDS_GAME_TEXT = "Swords"; + +const char *const WEEK_DAY_STRINGS[10] = { + "Ten", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine" +}; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 70fdcf65b1..8beeb56442 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -248,6 +248,34 @@ extern const char *const SPELL_DETAILS; extern const char *const MAP_TEXT; +extern const char *const LIGHT_COUNT_TEXT; + +extern const char *const FIRE_RESISTENCE_TEXT; + +extern const char *const ELECRICITY_RESISTENCE_TEXT; + +extern const char *const COLD_RESISTENCE_TEXT; + +extern const char *const POISON_RESISTENCE_TEXT; + +extern const char *const CLAIRVOYANCE_TEXT; + +extern const char *const LEVITATE_TEXT; + +extern const char *const WALK_ON_WATER_TEXT; + +extern const char *const GAME_INFORMATION; + +extern const char *const WORLD_GAME_TEXT; + +extern const char *const DARKSIDE_GAME_TEXT; + +extern const char *const CLOUDS_GAME_TEXT; + +extern const char *const SWORDS_GAME_TEXT; + +extern const char *const WEEK_DAY_STRINGS[10]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From d3e3093b035bb0e13492098e3f304474d0886fa4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 31 Jan 2015 17:45:06 -0500 Subject: XEEN: Add missing moveMonsters flag setting for automap and info dialogs --- engines/xeen/interface.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 3e958b391c..0ea5a8df83 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -672,12 +672,16 @@ void Interface::perform() { case Common::KEYCODE_EQUALS: case Common::KEYCODE_KP_EQUALS: // Toggle minimap + _vm->_moveMonsters = false; party._automapOn = !party._automapOn; + _vm->_moveMonsters = true; break; case Common::KEYCODE_i: // Show Info dialog + _vm->_moveMonsters = false; InfoDialog::show(_vm); + _vm->_moveMonsters = true; break; case Common::KEYCODE_m: -- cgit v1.2.3 From d855aa0dab588f2993a4c4f103a4632a9f0ba278 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 1 Feb 2015 11:56:08 -0500 Subject: XEEN: Implemented Character Info dialog --- engines/xeen/dialogs_automap.cpp | 3 +- engines/xeen/dialogs_char_info.cpp | 567 +++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_char_info.h | 58 ++++ engines/xeen/dialogs_spells.cpp | 18 +- engines/xeen/interface.cpp | 17 +- engines/xeen/interface_map.cpp | 2 +- engines/xeen/items.cpp | 1 + engines/xeen/items.h | 1 + engines/xeen/module.mk | 1 + engines/xeen/party.cpp | 47 ++- engines/xeen/party.h | 19 +- engines/xeen/resources.cpp | 111 +++++++- engines/xeen/resources.h | 51 +++- engines/xeen/town.h | 2 +- engines/xeen/xeen.h | 3 +- 15 files changed, 869 insertions(+), 32 deletions(-) create mode 100644 engines/xeen/dialogs_char_info.cpp create mode 100644 engines/xeen/dialogs_char_info.h (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_automap.cpp b/engines/xeen/dialogs_automap.cpp index 61821425dd..d9b7e8d6c7 100644 --- a/engines/xeen/dialogs_automap.cpp +++ b/engines/xeen/dialogs_automap.cpp @@ -40,7 +40,6 @@ void AutoMapDialog::execute() { Map &map = *_vm->_map; Party &party = *_vm->_party; int frame2 = intf._overallFrame * 2; - int varSI = 1; bool frameEndFlag = false; Common::Point pt = party._mazePosition; @@ -74,7 +73,7 @@ void AutoMapDialog::execute() { } screen._windows[5].open(); - MazeData &mazeData = map.mazeDataCurrent(); +// MazeData &mazeData = map.mazeDataCurrent(); bool drawFlag = true; int v; diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp new file mode 100644 index 0000000000..3ff40034a3 --- /dev/null +++ b/engines/xeen/dialogs_char_info.cpp @@ -0,0 +1,567 @@ +/* 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 "xeen/dialogs_char_info.h" +#include "xeen/resources.h" +#include "xeen/xeen.h" + +namespace Xeen { + +void CharacterInfo::show(XeenEngine *vm, int charIndex) { + CharacterInfo *dlg = new CharacterInfo(vm); + dlg->execute(charIndex); + delete dlg; +} + +void CharacterInfo::execute(int charIndex) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + + bool redrawFlag = false; + Mode oldMode = _vm->_mode; + _vm->_mode = MODE_CHARACTER_INFO; + loadDrawStructs(); + addButtons(); + + Character *c = (oldMode != MODE_InCombat) ? &party._activeParty[charIndex] : party._combatParty[charIndex]; + intf.highlightChar(charIndex); + Window &w = screen._windows[24]; + w.open(); + + do { + if (redrawFlag) { + Common::String charDetails = loadCharacterDetails(*c); + w.writeString(Common::String::format(CHARACTER_TEMPLATE, charDetails.c_str())); + w.drawList(_drawList, 24); + w.update(); + redrawFlag = false; + } + + // Wait for keypress, showing a blinking cursor + events.updateGameCounter(); + bool cursorFlag = false; + while (!_vm->shouldQuit() && !events.isKeyMousePressed()) { + if (events.timeElapsed() > 4) { + cursorFlag = !cursorFlag; + events.updateGameCounter(); + } + + showCursor(cursorFlag); + w.update(); + } + checkEvents(_vm); + events.clearEvents(); + + switch (_buttonValue) { + case Common::KEYCODE_F1: + case Common::KEYCODE_F2: + case Common::KEYCODE_F3: + case Common::KEYCODE_F4: + case Common::KEYCODE_F5: + case Common::KEYCODE_F6: + _buttonValue -= Common::KEYCODE_F1; + if (_buttonValue < (int)(oldMode == MODE_InCombat ? party._combatParty.size() : party._activeParty.size())) { + charIndex = _buttonValue; + c = (oldMode != MODE_InCombat) ? &party._activeParty[charIndex] : party._combatParty[charIndex]; + } + else { + _iconSprites.load("view.icn"); + _vm->_mode = MODE_CHARACTER_INFO; + } + break; + + case Common::KEYCODE_UP: + case Common::KEYCODE_KP8: + if (_cursorCell > 0) { + showCursor(false); + --_cursorCell; + showCursor(true); + } + w.update(); + break; + + case Common::KEYCODE_DOWN: + case Common::KEYCODE_KP2: + if (_cursorCell < 20) { + showCursor(false); + ++_cursorCell; + showCursor(true); + } + w.update(); + break; + + case Common::KEYCODE_LEFT: + case Common::KEYCODE_KP4: + if (_cursorCell >= 5) { + showCursor(false); + _cursorCell -= 5; + showCursor(true); + } + w.update(); + break; + + case Common::KEYCODE_RIGHT: + case Common::KEYCODE_KP6: + if (_cursorCell <= 15) { + showCursor(false); + _cursorCell += 5; + showCursor(true); + } + w.update(); + break; + + case Common::KEYCODE_RETURN: + case Common::KEYCODE_KP_ENTER: + _buttonValue = _cursorCell + Common::KEYCODE_a; + // Deliberate fall-through + + case 1001: + case 1002: + case 1003: + case 1004: + case 1005: + case 1006: + case 1007: + case 1008: + case 1009: + case 1010: + case 1011: + case 1012: + case 1013: + case 1014: + case 1015: + case 1016: + case 1017: + case 1018: + case 1019: + case 1020: { + showCursor(false); + _cursorCell = _buttonValue - 1001; + showCursor(true); + w.update(); + + bool result = expandStat(_cursorCell, *c); + _vm->_mode = MODE_InCombat; + if (result) + redrawFlag = true; + break; + } + + case Common::KEYCODE_e: + if (oldMode == MODE_InCombat) { + ErrorScroll::show(_vm, EXCHANGING_IN_COMBAT, WT_FREEZE_WAIT); + } else { + _vm->_mode = oldMode; + error("c = exchangeChar(&charIndex)"); + _vm->_mode = MODE_CHARACTER_INFO; + redrawFlag = true; + } + break; + + case Common::KEYCODE_i: + _vm->_mode = oldMode; + _vm->_treasure._v1 = _vm->_mode == MODE_InCombat; + error("TODO: c = ItemDialog::show"); + + if (!c) { + party._stepped = true; + goto exit; + } + + _vm->_mode = MODE_CHARACTER_INFO; + break; + + case Common::KEYCODE_ESCAPE: + goto exit; + } + } while (!_vm->shouldQuit()); +exit: + w.close(); + intf.unhighlightChar(); + _vm->_mode = oldMode; + _vm->_treasure._v1 = false; +} + +/** + * Load the draw structure list with frame numbers and positions + */ +void CharacterInfo::loadDrawStructs() { + _drawList[0] = DrawStruct(0, 2, 16); + _drawList[1] = DrawStruct(2, 2, 39); + _drawList[2] = DrawStruct(4, 2, 62); + _drawList[3] = DrawStruct(6, 2, 85); + _drawList[4] = DrawStruct(8, 2, 108); + _drawList[5] = DrawStruct(10, 53, 16); + _drawList[6] = DrawStruct(12, 53, 39); + _drawList[7] = DrawStruct(14, 53, 62); + _drawList[8] = DrawStruct(16, 53, 85); + _drawList[9] = DrawStruct(18, 53, 108); + _drawList[10] = DrawStruct(20, 104, 16); + _drawList[11] = DrawStruct(22, 104, 39); + _drawList[12] = DrawStruct(24, 104, 62); + _drawList[13] = DrawStruct(26, 104, 85); + _drawList[14] = DrawStruct(28, 104, 108); + _drawList[15] = DrawStruct(30, 169, 16); + _drawList[16] = DrawStruct(32, 169, 39); + _drawList[17] = DrawStruct(34, 169, 62); + _drawList[18] = DrawStruct(36, 169, 85); + _drawList[19] = DrawStruct(38, 169, 108); + _drawList[20] = DrawStruct(40, 277, 3); + _drawList[21] = DrawStruct(42, 277, 35); + _drawList[22] = DrawStruct(44, 277, 67); + _drawList[23] = DrawStruct(46, 277, 99); + + _iconSprites.load("view.icn"); + for (int idx = 0; idx < 24; ++idx) + _drawList[idx]._sprites = &_iconSprites; +} + +/** + * Set up the button list for the dialog + */ +void CharacterInfo::addButtons() { + addButton(Common::Rect(10, 24, 34, 64), 1001, &_iconSprites); + addButton(Common::Rect(10, 47, 34, 67), 1002, &_iconSprites); + addButton(Common::Rect(10, 70, 34, 90), 1003, &_iconSprites); + addButton(Common::Rect(10, 93, 34, 113), 1004, &_iconSprites); + addButton(Common::Rect(10, 116, 34, 136), 1005, &_iconSprites); + addButton(Common::Rect(61, 24, 85, 44), 1006, &_iconSprites); + addButton(Common::Rect(61, 47, 85, 67), 1007, &_iconSprites); + addButton(Common::Rect(61, 70, 85, 90), 1008, &_iconSprites); + addButton(Common::Rect(61, 93, 85, 113), 1009, &_iconSprites); + addButton(Common::Rect(61, 116, 85, 136), 1010, &_iconSprites); + addButton(Common::Rect(112, 24, 136, 44), 1011, &_iconSprites); + addButton(Common::Rect(112, 47, 136, 67), 1012, &_iconSprites); + addButton(Common::Rect(112, 70, 136, 90), 1013, &_iconSprites); + addButton(Common::Rect(112, 93, 136, 113), 1014, &_iconSprites); + addButton(Common::Rect(112, 116, 136, 136), 1015, &_iconSprites); + addButton(Common::Rect(177, 24, 201, 44), 1016, &_iconSprites); + addButton(Common::Rect(177, 47, 201, 67), 1017, &_iconSprites); + addButton(Common::Rect(177, 70, 201, 90), 1018, &_iconSprites); + addButton(Common::Rect(177, 93, 201, 113), 1019, &_iconSprites); + addButton(Common::Rect(177, 116, 201, 136), 1020, &_iconSprites); + addButton(Common::Rect(285, 11, 309, 31), Common::KEYCODE_i, &_iconSprites); + addButton(Common::Rect(285, 43, 309, 63), Common::KEYCODE_q, &_iconSprites); + addButton(Common::Rect(285, 75, 309, 95), Common::KEYCODE_e, &_iconSprites); + addButton(Common::Rect(285, 107, 309, 127), Common::KEYCODE_ESCAPE, &_iconSprites); +} + +/** + * Return a string containing the details of the character + */ +Common::String CharacterInfo::loadCharacterDetails(const Character &c) { + Condition condition = c.worstCondition(); + Party &party = *_vm->_party; + int foodVal = party._food / party._partyCount / 3; + + int totalResist = + c._fireResistence._permanent + c.itemScan(11) + c._fireResistence._temporary + + c._coldResistence._permanent + c.itemScan(13) + c._coldResistence._temporary + + c._electricityResistence._permanent + c.itemScan(12) + c._electricityResistence._temporary + + c._poisonResistence._permanent + c.itemScan(14) + c._poisonResistence._temporary + + c._energyResistence._permanent + c.itemScan(15) + c._energyResistence._temporary + + c._magicResistence._permanent + c.itemScan(16) + c._magicResistence._temporary; + + return Common::String::format(CHARACTER_DETAILS, + PARTY_GOLD, c._name.c_str(), SEX_NAMES[c._sex], + RACE_NAMES[c._race], CLASS_NAMES[c._class], + c.statColor(c.getStat(MIGHT), c.getStat(MIGHT, true)), c.getStat(MIGHT), + c.statColor(c.getStat(ACCURACY), c.getStat(ACCURACY, true)), c.getStat(ACCURACY), + c.statColor(c._currentHp, c.getMaxHP()), + c.getCurrentExperience(), + c.statColor(c.getStat(INTELLECT), c.getStat(INTELLECT, true)), c.getStat(INTELLECT), + c.statColor(c.getStat(LUCK), c.getStat(LUCK, true)), c.getStat(LUCK), + c.statColor(c._currentSp, c.getMaxSP()), c._currentSp, + party._gold, + c.statColor(c.getStat(PERSONALITY), c.getStat(PERSONALITY, true)), c.getStat(PERSONALITY), + c.statColor(c.getAge(), c.getAge(true)), c.getAge(), + totalResist, + party._gems, + c.statColor(c.getStat(ENDURANCE), c.getStat(ENDURANCE, true)), c.getStat(ENDURANCE), + c.statColor(c.getCurrentLevel(), c._level._permanent), c.getCurrentLevel(), + c.getNumSkills(), + foodVal, (foodVal == 1) ? ' ' : 's', + c.statColor(c.getStat(SPEED), c.getStat(SPEED, true)), c.getStat(SPEED), + c.statColor(c.getArmorClass(), c.getArmorClass(true)), c.getArmorClass(), + c.getNumAwards(), + CONDITION_COLORS[condition], CONDITION_NAMES[condition], + condition == NO_CONDITION && party._blessed ? PLUS_14 : "", + condition == NO_CONDITION && party._powerShield ? PLUS_14 : "", + condition == NO_CONDITION && party._holyBonus ? PLUS_14 : "", + condition == NO_CONDITION && party._heroism ? PLUS_14 : "" + ); +} + +/** + * Cursor display handling + */ +void CharacterInfo::showCursor(bool flag) { + Screen &screen = *_vm->_screen; + const int CURSOR_X[5] = { 9, 60, 111, 176, 0 }; + const int CURSOR_Y[5] = { 23, 46, 69, 92, 115 }; + + if (_cursorCell < 20) { + _iconSprites.draw(screen, flag ? 49 : 48, + Common::Point(CURSOR_X[_cursorCell / 5], CURSOR_Y[_cursorCell % 5])); + } +} + +bool CharacterInfo::expandStat(int attrib, const Character &c) { + const int STAT_POS[2][20] = { + { + 61, 61, 61, 61, 61, 112, 112, 112, 112, 112, + 177, 177, 177, 177, 177, 34, 34, 34, 34, 34 + }, { + 24, 47, 70, 93, 116, 24, 47, 70, 93, 116, + 24, 47, 70, 93, 116, 24, 47, 70, 93, 116 + } + }; + assert(attrib < 20); + Common::Rect bounds(STAT_POS[0][attrib], STAT_POS[1][attrib], + STAT_POS[0][attrib] + 143, STAT_POS[1][attrib] + 52); + Party &party = *_vm->_party; + int stat1, stat2; + uint idx; + Common::String msg; + + switch (attrib) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + // Basic attributes + stat1 = c.getStat((Attribute)attrib, false); + stat2 = c.getStat((Attribute)attrib, true); + idx = 0; + while (STAT_VALUES[idx] <= stat1) + ++idx; + + msg = Common::String::format(CURRENT_MAXIMUM_RATING_TEXT, STAT_NAMES[attrib], + stat1, stat2, RATING_TEXT[idx]); + break; + + case 7: + // Age + stat1 = c.getAge(false); + stat2 = c.getAge(true); + msg = Common::String::format(AGE_TEXT, STAT_NAMES[attrib], + stat2, c._dbDay, c._ybDay); + break; + + case 8: { + // Level + const int CLASS_ATTACK_GAINS[10] = { 5, 6, 6, 7, 8, 6, 5, 4, 7, 6 }; + idx = c.getCurrentLevel() / CLASS_ATTACK_GAINS[c._class] + 1; + + msg = Common::String::format(LEVEL_TEXT, STAT_NAMES[attrib], + c.getCurrentLevel(), c._level._permanent, + idx, idx > 1 ? "s" : "", + c._level._permanent); + break; + } + + case 9: + // Armor Class + stat1 = c.getArmorClass(false); + stat2 = c.getArmorClass(true); + msg = Common::String::format(CURRENT_MAXIMUM_TEXT, STAT_NAMES[attrib], + stat1, stat2); + bounds.setHeight(42); + break; + + case 10: + // Hit Points + stat1 = c._currentHp; + stat2 = c.getMaxHP(); + msg = Common::String::format(CURRENT_MAXIMUM_TEXT, STAT_NAMES[attrib], + stat1, stat2); + bounds.setHeight(42); + break; + + case 11: + // Spell Points + stat1 = c._currentSp; + stat2 = c.getMaxSP(); + msg = Common::String::format(CURRENT_MAXIMUM_TEXT, STAT_NAMES[attrib], + stat1, stat2); + bounds.setHeight(42); + break; + + case 12: + // Resistences + msg = Common::String::format(RESISTENCES_TEXT, STAT_NAMES[attrib], + c._fireResistence._permanent + c.itemScan(11) + c._fireResistence._temporary, + c._coldResistence._permanent + c.itemScan(13) + c._coldResistence._temporary, + c._electricityResistence._permanent + c.itemScan(12) + c._electricityResistence._temporary, + c._poisonResistence._permanent + c.itemScan(14) + c._poisonResistence._temporary, + c._energyResistence._permanent + c.itemScan(15) + c._energyResistence._temporary, + c._magicResistence._permanent + c.itemScan(16) + c._magicResistence._temporary); + break; + + case 13: { + // Skills + Common::String lines[20]; + int numLines = c.getNumSkills(); + if (numLines > 0) { + for (int skill = THIEVERY; skill <= DANGER_SENSE; ++skill) { + if (c._skills[skill]) { + if (skill == THIEVERY) { + lines[0] = Common::String::format("\n\t020%s%u", + SKILL_NAMES[THIEVERY], c.getThievery()); + } else { + lines[skill] = Common::String::format("\n\t020%s", SKILL_NAMES[skill]); + } + } + } + } else { + lines[0] = NONE; + numLines = 1; + } + + msg = Common::String::format("\x2\x3""c%s\x3l%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + STAT_NAMES[attrib], lines[0].c_str(), lines[1].c_str(), + lines[2].c_str(), lines[3].c_str(), lines[4].c_str(), lines[5].c_str(), + lines[17].c_str(), lines[6].c_str(), lines[7].c_str(), lines[8].c_str(), + lines[9].c_str(), lines[10].c_str(), lines[11].c_str(), lines[12].c_str(), + lines[13].c_str(), lines[16].c_str(), lines[14].c_str(), lines[15].c_str()); + + bounds.top -= (numLines / 2) * 8; + bounds.setHeight(numLines * 9 + 26); + if (bounds.bottom >= SCREEN_HEIGHT) + bounds.moveTo(bounds.left, SCREEN_HEIGHT - bounds.height() - 1); + break; + } + + case 14: + // Awards + error("AwardsDialog::show"); + return false; + + case 15: + // Experience + stat1 = c.getCurrentExperience(); + stat2 = c.nextExperienceLevel(); + msg = Common::String::format(EXPERIENCE_TEXT, + STAT_NAMES[attrib], stat1, + stat2 == 0 ? ELIGIBLE : Common::String::format("%d", stat2) + ); + bounds.setHeight(43); + break; + + case 16: + // Gold + msg = Common::String::format(IN_PARTY_IN_BANK, STAT_NAMES[attrib], + party._gold, party._bankGold); + break; + + case 17: + // Gems + msg = Common::String::format(IN_PARTY_IN_BANK, STAT_NAMES[attrib], + party._gems, party._bankGems); + bounds.setHeight(43); + break; + + case 18: { + // Food + int food = (party._food / party._partyCount) / 3; + msg = Common::String::format(FOOD_TEXT, STAT_NAMES[attrib], + party._food, food, food != 1 ? "s" : ""); + break; + } + + case 19: { + // Conditions + Common::String lines[20]; + int total = 0; + for (int condition = CURSED; condition <= ERADICATED; ++condition) { + if (c._conditions[condition]) { + if (condition >= UNCONSCIOUS) { + lines[condition] = Common::String::format("\n\t020%s", + CONDITION_NAMES[condition]); + } else { + lines[condition] = Common::String::format("\n\t020%s\t095-%d", + CONDITION_NAMES[condition], c._conditions[condition]); + } + + ++total; + } + } + + Condition condition = c.worstCondition(); + if (condition == NO_CONDITION) { + lines[0] = Common::String::format("\n\t020%s", GOOD); + } + + if (party._blessed) + lines[16] = Common::String::format(BLESSED, party._blessed); + if (party._powerShield) + lines[17] = Common::String::format(POWER_SHIELD, party._powerShield); + if (party._holyBonus) + lines[18] = Common::String::format(HOLY_BONUS, party._holyBonus); + if (party._heroism) + lines[19] = Common::String::format(HEROISM, party._heroism); + + msg = Common::String::format("\x2\x3""c%s\x3l%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\x1", + STAT_NAMES[attrib], lines[0].c_str(), lines[1].c_str(), + lines[2].c_str(), lines[3].c_str(), lines[4].c_str(), + lines[5].c_str(), lines[6].c_str(), lines[7].c_str(), + lines[8].c_str(), lines[9].c_str(), lines[10].c_str(), + lines[11].c_str(), lines[12].c_str(), lines[13].c_str(), + lines[14].c_str(), lines[15].c_str(), lines[16].c_str(), + lines[17].c_str(), lines[18].c_str(), lines[19].c_str() + ); + + bounds.top = ((total - 1) / 2) * 8; + bounds.setHeight(total * 9 + 26); + if (bounds.bottom >= SCREEN_HEIGHT) + bounds.moveTo(bounds.left, SCREEN_HEIGHT - bounds.height() - 1); + break; + } + + default: + break; + } + + // Write the data for the stat display + Window &w = _vm->_screen->_windows[28]; + w.setBounds(bounds); + w.open(); + w.writeString(msg); + w.update(); + + // Wait for a user key/click + EventsManager &events = *_vm->_events; + while (!_vm->shouldQuit() && !events.isKeyMousePressed()) + events.pollEventsAndWait(); + events.clearEvents(); + + w.close(); + return false; +} + + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_char_info.h b/engines/xeen/dialogs_char_info.h new file mode 100644 index 0000000000..5a20ff2248 --- /dev/null +++ b/engines/xeen/dialogs_char_info.h @@ -0,0 +1,58 @@ +/* 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 XEEN_DIALOGS_CHAR_INFO_H +#define XEEN_DIALOGS_CHAR_INFO_H + +#include "xeen/dialogs.h" +#include "xeen/party.h" +#include "xeen/screen.h" + +namespace Xeen { + +class CharacterInfo : public ButtonContainer { +private: + XeenEngine *_vm; + SpriteResource _iconSprites; + DrawStruct _drawList[24]; + int _cursorCell; + + CharacterInfo(XeenEngine *vm) : ButtonContainer(), _vm(vm), _cursorCell(0) {} + + void execute(int charIndex); + + void loadDrawStructs(); + + void addButtons(); + + Common::String loadCharacterDetails(const Character &c); + + void showCursor(bool flag); + + bool expandStat(int attrib, const Character &c); +public: + static void show(XeenEngine *vm, int charIndex); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_CHAR_INFO_H */ diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 7ae5e7ad90..714e881128 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -50,7 +50,7 @@ Character *SpellsScroll::execute(Character *c, int v2) { int v2Copy = v2; v2 &= 0x7f; int selection = -1; - int topIndex = 0; + uint topIndex = 0; int newSelection; screen._windows[25].open(); @@ -109,7 +109,7 @@ Character *SpellsScroll::execute(Character *c, int v2) { switch (_buttonValue) { case Common::KEYCODE_F1: case Common::KEYCODE_F6: - if (_vm->_mode != MODE_2) { + if (_vm->_mode != MODE_InCombat) { _buttonValue -= Common::KEYCODE_F1; if (_buttonValue < party._partyCount) { c = &party._activeParty[_buttonValue]; @@ -233,12 +233,12 @@ Character *SpellsScroll::execute(Character *c, int v2) { case Common::KEYCODE_PAGEUP: case Common::KEYCODE_KP9: - topIndex = MAX(topIndex - 10, 0); + topIndex = MAX((int)topIndex - 10, 0); break; case Common::KEYCODE_PAGEDOWN: case Common::KEYCODE_KP3: - topIndex = MIN(topIndex + 10, (((int)_spells.size() - 1) / 10) * 10); + topIndex = MIN(topIndex + 10, ((_spells.size() - 1) / 10) * 10); break; case Common::KEYCODE_UP: @@ -249,7 +249,7 @@ Character *SpellsScroll::execute(Character *c, int v2) { case Common::KEYCODE_DOWN: case Common::KEYCODE_KP2: - if (topIndex < ((int)_spells.size() - 10)) + if (topIndex < (_spells.size() - 10)) ++topIndex; break; } @@ -321,7 +321,7 @@ const char *SpellsScroll::setSpellText(Character *c, int v2) { if (category != -1) { if (party._mazeId == 49 || party._mazeId == 37) { - for (int spellId = 0; spellId < 76; ++spellId) { + for (uint spellId = 0; spellId < 76; ++spellId) { int idx = 0; while (idx < MAX_SPELLS_PER_CLASS && SPELLS_ALLOWED[category][idx] == spellId) ++idx; @@ -338,8 +338,8 @@ const char *SpellsScroll::setSpellText(Character *c, int v2) { } } else if (isDarkCc) { int groupIndex = (party._mazeId - 29) / 2; - for (int spellId = DARK_SPELL_RANGES[category][0]; - spellId < DARK_SPELL_RANGES[category][1]; ++spellId) { + for (int spellId = DARK_SPELL_RANGES[groupIndex][0]; + spellId < DARK_SPELL_RANGES[groupIndex][1]; ++spellId) { int idx = 0; while (idx < 40 && SPELLS_ALLOWED[category][idx] == DARK_SPELL_OFFSETS[category][spellId]); @@ -357,7 +357,7 @@ const char *SpellsScroll::setSpellText(Character *c, int v2) { for (int spellId = 0; spellId < 20; ++spellId) { int idx = 0; while (CLOUDS_SPELL_OFFSETS[party._mazeId - 29][spellId] != - SPELLS_ALLOWED[category][idx] && idx < 40) ; + (int)SPELLS_ALLOWED[category][idx] && idx < 40) ; if (idx < 40) { if (!c->_spells[idx] || (v2 & 0x80)) { diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 0ea5a8df83..a33c726fd3 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -21,6 +21,7 @@ */ #include "xeen/interface.h" +#include "xeen/dialogs_char_info.h" #include "xeen/dialogs_error.h" #include "xeen/dialogs_automap.h" #include "xeen/dialogs_info.h" @@ -331,7 +332,7 @@ void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool void Interface::charIconsPrint(bool updateFlag) { Screen &screen = *_vm->_screen; - bool stateFlag = _vm->_mode == MODE_2; + bool stateFlag = _vm->_mode == MODE_InCombat; _restoreSprites.draw(screen, 0, Common::Point(8, 149)); // Handle drawing the party faces @@ -669,6 +670,20 @@ void Interface::perform() { } break; + case Common::KEYCODE_F1: + case Common::KEYCODE_F2: + case Common::KEYCODE_F3: + case Common::KEYCODE_F4: + case Common::KEYCODE_F5: + case Common::KEYCODE_F6: + _buttonValue -= Common::KEYCODE_F1; + if (_buttonValue < party._partyCount) { + CharacterInfo::show(_vm, _buttonValue); + if (party._stepped) + moveMonsters(); + } + break; + case Common::KEYCODE_EQUALS: case Common::KEYCODE_KP_EQUALS: // Toggle minimap diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 84f8fa6aa1..c8683a7e50 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -426,7 +426,7 @@ void InterfaceMap::draw3d(bool updateFlag) { _flipUIFrame = (_flipUIFrame + 1) % 4; if (_flipUIFrame == 0) _flipWater = !_flipWater; - if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_2) && + if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_InCombat) && !_flag1 && _vm->_moveMonsters) { if (--_tillMove == 0) moveMonsters(); diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp index f7dfeccbb1..c55a227502 100644 --- a/engines/xeen/items.cpp +++ b/engines/xeen/items.cpp @@ -56,6 +56,7 @@ int XeenItem::getAttributeCategory() const { Treasure::Treasure() { _hasItems = false; + _v1 = false; } } // End of namespace Xeen diff --git a/engines/xeen/items.h b/engines/xeen/items.h index 958a0b8afc..8e8f172790 100644 --- a/engines/xeen/items.h +++ b/engines/xeen/items.h @@ -55,6 +55,7 @@ public: XeenItem _armor[TOTAL_ITEMS]; XeenItem _weapons[TOTAL_ITEMS]; bool _hasItems; + bool _v1; public: Treasure(); }; diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 4bb8bd99c0..6a9ff3012c 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -10,6 +10,7 @@ MODULE_OBJS := \ dialogs.o \ automap.o \ dialogs_automap.o \ + dialogs_char_info.o \ dialogs_confirm.o \ dialogs_error.o \ dialogs_options.o \ diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 66078b67e8..3cfc56e1ec 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -238,7 +238,7 @@ int Character::getMaxSP() const { /** * Get the effective value of a given stat for the character */ -int Character::getStat(Attribute attrib, bool baseOnly) const { +uint Character::getStat(Attribute attrib, bool baseOnly) const { AttributePair attr; int mode = 0; @@ -289,7 +289,24 @@ int Character::getStat(Attribute attrib, bool baseOnly) const { attr._permanent += attr._temporary; } - return MAX(attr._permanent, 0); + return MAX(attr._permanent, (uint)0); +} + +/** + * Return the color number to use for a given stat value in the character + * info or quick reference dialogs + */ +int Character::statColor(int amount, int threshold) { + if (amount < 1) + return 6; + else if (amount > threshold) + return 2; + else if (amount == threshold) + return 15; + else if (amount <= (threshold / 4)) + return 9; + else + return 32; } int Character::statBonus(int statValue) const { @@ -422,8 +439,8 @@ int Character::getThievery() const { return MAX(result, 0); } -int Character::getCurrentLevel() const { - return MAX(_level._permanent + _level._temporary, 0); +uint Character::getCurrentLevel() const { + return MAX(_level._permanent + _level._temporary, (uint)0); } int Character::itemScan(int itemId) const { @@ -817,6 +834,28 @@ uint Character::getCurrentExperience() const { _experience; } + +int Character::getNumSkills() const { + int total = 0; + for (int idx = THIEVERY; idx <= DANGER_SENSE; ++idx) { + if (_skills[idx]) + ++total; + } + + return total; +} + +int Character::getNumAwards() const { + int total = 0; + for (int idx = 0; idx < 88; ++idx) { + if (hasAward(idx)) + ++total; + } + + return total; +} + + /*------------------------------------------------------------------------*/ void Roster::synchronize(Common::Serializer &s) { diff --git a/engines/xeen/party.h b/engines/xeen/party.h index e00b42476a..b793b5c696 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -80,8 +80,8 @@ class XeenEngine; class AttributePair { public: - int _permanent; - int _temporary; + uint _permanent; + uint _temporary; public: AttributePair(); void synchronize(Common::Serializer &s); @@ -141,13 +141,15 @@ public: Condition worstCondition() const; - int getAge(bool ignoreTemp) const; + int getAge(bool ignoreTemp = false) const; int getMaxHP() const; int getMaxSP() const; - int getStat(Attribute attrib, bool baseOnly = false) const; + uint getStat(Attribute attrib, bool baseOnly = false) const; + + static int statColor(int amount, int threshold); int statBonus(int statValue) const; @@ -159,11 +161,11 @@ public: bool hasAward(int awardId) const; - int getArmorClass(bool baseOnly) const; + int getArmorClass(bool baseOnly = false) const; int getThievery() const; - int getCurrentLevel() const; + uint getCurrentLevel() const; int itemScan(int itemId) const; @@ -176,6 +178,10 @@ public: uint currentExperienceLevel() const; uint getCurrentExperience() const; + + int getNumSkills() const; + + int getNumAwards() const; }; class Roster: public Common::Array<Character> { @@ -247,6 +253,7 @@ public: public: // Other party related runtime data Common::Array<Character> _activeParty; + Common::Array<Character *> _combatParty; int _combatPartyCount; bool _partyDead; bool _newDay; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index dafe321ab5..4e958a155d 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -287,6 +287,13 @@ const char *const ALIGNMENT_NAMES[3] = { "Good", "Neutral", "Evil" }; const char *const SEX_NAMES[2] = { "Male", "Female" }; +const char *const SKILL_NAMES[18] = { + "Thievery", "Arms Master", "Astrologer", "Body Builder", "Cartographer", + "Crusader", "Direction Sense", "Linguist", "Merchant", "Mountaineer", + "Navigator", "Path Finder", "Prayer Master", "Prestidigitator", + "Swimmer", "Tracker", "Spot Secret Door", "Danger Sense" +}; + const char *const CLASS_NAMES[11] = { "Knight", "Paladin", "Archer", "Cleric", "Sorcerer", "Robber", "Ninja", "Barbarian", "Druid", "Ranger", nullptr @@ -296,12 +303,26 @@ const uint CLASS_EXP_LEVELS[10] = { 1500, 2000, 2000, 1500, 2000, 1000, 1500, 1500, 1500, 2000 }; -const char *const CONDITION_NAMES[18] = { +const char *const CONDITION_NAMES[17] = { nullptr, "Cursed", "Heart Broken", "Weak", "Poisoned", "Diseased", "Insane", "In Love", "Drunk", "Asleep", "Depressed", "Confused", - "Paralyzed", "Unconscious", "Dead", "Stone", "Eradicated", "Good" + "Paralyzed", "Unconscious", "Dead", "Stone", "Eradicated" }; +const int CONDITION_COLORS[17] = { + 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 6, 6, 6, 6, 15 +}; + +const char *const GOOD = "Good"; + +const char *const BLESSED = "\n\t020Blessed\t095%+d"; + +const char *const POWER_SHIELD = "\n\t020Power Shield\t095%+d"; + +const char *const HOLY_BONUS = "\n\t020Holy Bonus\t095%+d"; + +const char *const HEROISM = "\n\t020Heroism\t095%+d"; + const char *const IN_PARTY = "\014""15In Party\014""d"; const char *const PARTY_DETAILS = "\015\003l\002\014""00" @@ -494,7 +515,7 @@ const int MONSTER_EFFECT_FLAGS[15][8] = { { 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108 } }; -const int SPELLS_ALLOWED[3][40] = { +const uint SPELLS_ALLOWED[3][40] = { { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 14, 16, 23, 26, 27, 28, 30, 31, 32, @@ -760,7 +781,7 @@ const int CLOUDS_SPELL_OFFSETS[5][20] = { } }; -const int DARK_SPELL_OFFSETS[3][39] = { +const uint DARK_SPELL_OFFSETS[3][39] = { { 42, 1, 26, 59, 27, 10, 50, 68, 55, 62, 67, 73, 2, 5, 3, 31, 30, 52, 49, 28, 74, 0, 9, 7, 14, 8, @@ -866,4 +887,86 @@ const char *const WEEK_DAY_STRINGS[10] = { "Ten", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine" }; +const char *const CHARACTER_DETAILS = + "\x3l\xB""041\x9""196%s\x9""000\xB""002%s : %s %s %s" + "\x3r\x9""053\xB""028\xC%02u%u\xC""d\x9""103\xC""%02u%u\xC""d" + "\x3l\x9""131\xC""%02u%d\xC""d\x9""196\xC""15%lu\xC""d\x3r" + "\x9""053\xB""051\xC""%02u%u\xC""d\x9""103\xC""%02u%u\xC""d" + "\x3l\x9""131\xC""%02u%u\xC""d\x9""196\xC""15%lu\xC""d" + "\x3r\x9""053\xB""074\xC""%02u%u\xC""d\x9""103\xC""%02u%u\xC""d" + "\x3l\x9""131\xC""15%u\xC""d\x9""196\xC""15%lu\xC""d" + "\x3r\x9""053\xB""097\xC""%02u%u\xC""d\x9""103\xC""%02u%u\xC""d" + "\x3l\x9""131\xC""15%u\xC""d\x9""196\xC""15%u day%c\xC""d" + "\x3r\x9""053\xB""120\xC""%02u%u\xC""d\x9""103\xC""%02u%u\xC""d" + "\x3l\x9""131\xC""15%u\xC""d\x9""196\xC""%02u%s\xC""d" + "\x9""230%s%s%s%s\xC""d"; + +const char *const PARTY_GOLD = "Party Gold"; + +const char *const PLUS_14 = "14+"; + +const char *const CHARACTER_TEMPLATE = + "\x1\xC""00\xD\x3l\x9""029\xB""018Mgt\x9""080Acy\x9""131H.P.\x9""196Experience" + "\x9""029\xB""041Int\x9""080Lck\x9""131S.P.\x9""029\xB""064Per\x9""080Age" + "\x9""131Resis\x9""196Party Gems\x9""029\xB""087End\x9""080Lvl\x9""131Skills" + "\x9""196Party Food\x9""029\xB""110Spd\x9""080AC\x9""131Awrds\x9""196Condition\x3""c" + "\x9""290\xB""025\xC""37I\xC""dtem\x9""290\xB""057\xC""37Q" + "\xC""duick\x9""290\xB""089\xC""37E\xC""dxch\x9""290\xB""121Exit\x3l%s"; + +const char *const EXCHANGING_IN_COMBAT = "\x3""c\xB""007\x9""000Exchanging in combat is not allowed!"; + +const char *const CURRENT_MAXIMUM_RATING_TEXT = "\x2\x3""c%s\n" + "Current / Maximum\n" + "\x3r\x9""054%lu\x3l\x9""058/ %lu\n" + "\x3""cRating: %s"; + +const char *const CURRENT_MAXIMUM_TEXT = "\x2\x3""c%s\n" + "Current / Maximum\n" + "\x3r\x9""054%u\x3l\x9""058/ %u"; + +const char *const RATING_TEXT[24] = { + "Nonexistant", "Very Poor", "Poor", "Very Low", "Low", "Averarage", "Good", + "Very Good", "High", "Very High", "Great", "Super", "Amazing", "Incredible", + "Gigantic", "Fantastic", "Astoundig", "Astonishing", "Monumental", "Tremendous", + "Collosal", "Awesome", "AweInspiring", "aUltimate" +}; + +const char *const AGE_TEXT = "\x2\x3""c%s\n" + "Current / Natural\n" + "\x3r\x9""057%u\x3l\x9""061/ %u\n" + "\x3""cBorn: %u / %u\x1"; + +const char *const LEVEL_TEXT = + "\x2\x3""c%s\n" + "Current / Maximum\n" + "\x3r\x9""054%u\x3l\x9""058/ %u\n" + "\x3""c%u Attack%s/Round\x1"; + +const char *const RESISTENCES_TEXT = + "\x2\x3""c%s\x3l\n" + "\x9""020Fire\x9""100%u\n" + "\x9""020Cold\x9""100%u\n" + "\x9""020Electricity\x9""100%u\n" + "\x9""020Poison\x9""100%u\n" + "\x9""020Energy\x9""100%u\n" + "\x9""020Magic\x9""100%u"; + +const char *const NONE = "\n\x9""020"; + +const char *const EXPERIENCE_TEXT = "\x2\x3""c%s\x3l\n" + "\x9""010Current:\x9""070%lu\n" + "\x9""010Next Level:\x9""070%s\x1"; + +const char *const ELIGIBLE = "\xC""12Eligible\xC""d"; + +const char *const IN_PARTY_IN_BANK = + "\x2\x3""cParty %s\n" + "%lu on hand\n" + "%lu in bank\x1\x3l"; + +const char *const FOOD_TEXT = + "\x2\x3""cParty %s\n" + "%u on hand\n" + "Enough for %u day%s\x3l"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 8beeb56442..a696e540e1 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -74,8 +74,21 @@ extern const char *const ALIGNMENT_NAMES[3]; extern const char *const SEX_NAMES[2]; -extern const char *const CONDITION_NAMES[18]; +extern const char *const SKILL_NAMES[18]; +extern const char *const CONDITION_NAMES[17]; + +extern const int CONDITION_COLORS[17]; + +extern const char *const GOOD; + +extern const char *const BLESSED; + +extern const char *const POWER_SHIELD; + +extern const char *const HOLY_BONUS; + +extern const char *const HEROISM; extern const char *const IN_PARTY; extern const char *const PARTY_DETAILS; @@ -126,7 +139,7 @@ extern const int COMBAT_FLOAT_Y[8]; extern const int MONSTER_EFFECT_FLAGS[15][8]; -extern const int SPELLS_ALLOWED[3][40]; +extern const uint SPELLS_ALLOWED[3][40]; extern const int BASE_HP_BY_CLASS[10]; @@ -220,7 +233,7 @@ extern const int SPELL_COSTS[77]; extern const int CLOUDS_SPELL_OFFSETS[5][20]; -extern const int DARK_SPELL_OFFSETS[3][39]; +extern const uint DARK_SPELL_OFFSETS[3][39]; extern const int DARK_SPELL_RANGES[12][2]; @@ -276,6 +289,38 @@ extern const char *const SWORDS_GAME_TEXT; extern const char *const WEEK_DAY_STRINGS[10]; +extern const char *const CHARACTER_DETAILS; + +extern const char *const PARTY_GOLD; + +extern const char *const PLUS_14; + +extern const char *const CHARACTER_TEMPLATE; + +extern const char *const EXCHANGING_IN_COMBAT; + +extern const char *const CURRENT_MAXIMUM_RATING_TEXT; + +extern const char *const CURRENT_MAXIMUM_TEXT; + +extern const char *const RATING_TEXT[24]; + +extern const char *const AGE_TEXT; + +extern const char *const LEVEL_TEXT; + +extern const char *const RESISTENCES_TEXT; + +extern const char *const NONE; + +extern const char *const EXPERIENCE_TEXT; + +extern const char *const ELIGIBLE; + +extern const char *const IN_PARTY_IN_BANK; + +extern const char *const FOOD_TEXT; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/town.h b/engines/xeen/town.h index 8237f8102e..807f6b5138 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -47,7 +47,7 @@ private: int _v5, _v6; int _v10, _v11, _v12; int _v13, _v14; - int _v20; + uint _v20; int _v21; uint _v22; int _v23; diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index cb09c280cd..7f1a2cd0f0 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -77,7 +77,7 @@ enum Mode { MODE_FF = -1, MODE_0 = 0, MODE_1 = 1, - MODE_2 = 2, + MODE_InCombat = 2, MODE_3 = 3, MODE_4 = 4, MODE_5 = 5, @@ -85,6 +85,7 @@ enum Mode { MODE_7 = 7, MODE_8 = 8, MODE_9 = 9, + MODE_CHARACTER_INFO = 10, MODE_17 = 17 }; -- cgit v1.2.3 From 3ae4958f0ba6823b74cf86db6dbd905a8f2d4c47 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 1 Feb 2015 13:57:02 -0500 Subject: XEEN: Implemented Exchange character dialog --- engines/xeen/dialogs_char_info.cpp | 16 ++++---- engines/xeen/dialogs_exchange.cpp | 82 ++++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_exchange.h | 47 ++++++++++++++++++++++ engines/xeen/interface.h | 2 +- engines/xeen/module.mk | 1 + engines/xeen/resources.cpp | 2 + engines/xeen/resources.h | 2 + 7 files changed, 144 insertions(+), 8 deletions(-) create mode 100644 engines/xeen/dialogs_exchange.cpp create mode 100644 engines/xeen/dialogs_exchange.h (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp index 3ff40034a3..9fedb56fcf 100644 --- a/engines/xeen/dialogs_char_info.cpp +++ b/engines/xeen/dialogs_char_info.cpp @@ -21,6 +21,7 @@ */ #include "xeen/dialogs_char_info.h" +#include "xeen/dialogs_exchange.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -38,7 +39,7 @@ void CharacterInfo::execute(int charIndex) { Interface &intf = *_vm->_interface; Party &party = *_vm->_party; - bool redrawFlag = false; + bool redrawFlag = true; Mode oldMode = _vm->_mode; _vm->_mode = MODE_CHARACTER_INFO; loadDrawStructs(); @@ -60,8 +61,10 @@ void CharacterInfo::execute(int charIndex) { // Wait for keypress, showing a blinking cursor events.updateGameCounter(); - bool cursorFlag = false; - while (!_vm->shouldQuit() && !events.isKeyMousePressed()) { + bool cursorFlag = false; + _buttonValue = 0; + while (!_vm->shouldQuit() && !_buttonValue) { + events.pollEventsAndWait(); if (events.timeElapsed() > 4) { cursorFlag = !cursorFlag; events.updateGameCounter(); @@ -69,8 +72,8 @@ void CharacterInfo::execute(int charIndex) { showCursor(cursorFlag); w.update(); + checkEvents(_vm); } - checkEvents(_vm); events.clearEvents(); switch (_buttonValue) { @@ -84,8 +87,7 @@ void CharacterInfo::execute(int charIndex) { if (_buttonValue < (int)(oldMode == MODE_InCombat ? party._combatParty.size() : party._activeParty.size())) { charIndex = _buttonValue; c = (oldMode != MODE_InCombat) ? &party._activeParty[charIndex] : party._combatParty[charIndex]; - } - else { + } else { _iconSprites.load("view.icn"); _vm->_mode = MODE_CHARACTER_INFO; } @@ -173,7 +175,7 @@ void CharacterInfo::execute(int charIndex) { ErrorScroll::show(_vm, EXCHANGING_IN_COMBAT, WT_FREEZE_WAIT); } else { _vm->_mode = oldMode; - error("c = exchangeChar(&charIndex)"); + ExchangeDialog::show(_vm, c, charIndex); _vm->_mode = MODE_CHARACTER_INFO; redrawFlag = true; } diff --git a/engines/xeen/dialogs_exchange.cpp b/engines/xeen/dialogs_exchange.cpp new file mode 100644 index 0000000000..56a310a928 --- /dev/null +++ b/engines/xeen/dialogs_exchange.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 "xeen/dialogs_exchange.h" +#include "xeen/resources.h" +#include "xeen/xeen.h" + +namespace Xeen { + +void ExchangeDialog::show(XeenEngine *vm, Character *&c, int &charIndex) { + ExchangeDialog *dlg = new ExchangeDialog(vm); + dlg->execute(c, charIndex); + delete dlg; +} + +void ExchangeDialog::execute(Character *&c, int &charIndex) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + loadButtons(); + + Window &w = screen._windows[31]; + w.open(); + w.writeString(EXCHANGE_WITH_WHOM); + _iconSprites.draw(w, 0, Common::Point(225, 120)); + w.update(); + + while (!_vm->shouldQuit()) { + events.pollEventsAndWait(); + checkEvents(_vm); + + if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) { + _buttonValue -= Common::KEYCODE_F1; + if (_buttonValue < party._partyCount) { + SWAP(party._activeParty[charIndex], party._activeParty[_buttonValue]); + SWAP(party._partyMembers[charIndex], party._partyMembers[_buttonValue]); + SWAP(intf._partyFaces[charIndex], intf._partyFaces[_buttonValue]); + + charIndex = _buttonValue; + c = &party._activeParty[charIndex]; + break; + } + } else if (_buttonValue == Common::KEYCODE_ESCAPE) { + break; + } + } + + w.close(); + intf.charIconsPrint(true); + intf.highlightChar(charIndex); +} + +void ExchangeDialog::loadButtons() { + _iconSprites.load("esc.icn"); + addButton(Common::Rect(225, 120, 249, 245), Common::KEYCODE_ESCAPE, &_iconSprites, true); + addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_iconSprites, false); + addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_iconSprites, false); + addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3, &_iconSprites, false); + addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4, &_iconSprites, false); +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_exchange.h b/engines/xeen/dialogs_exchange.h new file mode 100644 index 0000000000..e8c4a2dfb1 --- /dev/null +++ b/engines/xeen/dialogs_exchange.h @@ -0,0 +1,47 @@ +/* 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 XEEN_DIALOGS_EXCHANGE_H +#define XEEN_DIALOGS_EXCHANGE_H + +#include "xeen/dialogs.h" +#include "xeen/party.h" + +namespace Xeen { + +class ExchangeDialog : public ButtonContainer { +private: + XeenEngine *_vm; + SpriteResource _iconSprites; + + ExchangeDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + void execute(Character *&c, int &charIndex); + + void loadButtons(); +public: + static void show(XeenEngine *vm, Character *&c, int &charIndex); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_EXCHANGE_H */ diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 73cd50977b..103b8b6607 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -45,7 +45,6 @@ private: SpriteResource _uiSprites; SpriteResource _iconSprites; SpriteResource _charFaces[TOTAL_CHARACTERS]; - SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; DrawStruct _faceDrawStructs[4]; DrawStruct _mainList[16]; int _combatCharIds[8]; @@ -78,6 +77,7 @@ private: public: int _intrIndex1; Common::String _interfaceText; + SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; public: Interface(XeenEngine *vm); diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 6a9ff3012c..8d3a5e52bf 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -13,6 +13,7 @@ MODULE_OBJS := \ dialogs_char_info.o \ dialogs_confirm.o \ dialogs_error.o \ + dialogs_exchange.o \ dialogs_options.o \ dialogs_info.o \ dialogs_input.o \ diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 4e958a155d..467dbe21f8 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -969,4 +969,6 @@ const char *const FOOD_TEXT = "%u on hand\n" "Enough for %u day%s\x3l"; +const char *const EXCHANGE_WITH_WHOM = "\t010\v005Exchange with whom?"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index a696e540e1..64387e7f54 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -321,6 +321,8 @@ extern const char *const IN_PARTY_IN_BANK; extern const char *const FOOD_TEXT; +extern const char *const EXCHANGE_WITH_WHOM; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From d57c9f20213e66539fc7686a8b8abc26090aaa59 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 1 Feb 2015 15:24:12 -0500 Subject: XEEN: Fixes to the Character Info dialog --- engines/xeen/dialogs_char_info.cpp | 4 ++-- engines/xeen/party.cpp | 4 ++-- engines/xeen/resources.cpp | 4 ++-- engines/xeen/screen.cpp | 7 +++++-- 4 files changed, 11 insertions(+), 8 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp index 9fedb56fcf..1c0d0bfe31 100644 --- a/engines/xeen/dialogs_char_info.cpp +++ b/engines/xeen/dialogs_char_info.cpp @@ -88,9 +88,9 @@ void CharacterInfo::execute(int charIndex) { charIndex = _buttonValue; c = (oldMode != MODE_InCombat) ? &party._activeParty[charIndex] : party._combatParty[charIndex]; } else { - _iconSprites.load("view.icn"); _vm->_mode = MODE_CHARACTER_INFO; } + redrawFlag = true; break; case Common::KEYCODE_UP: @@ -290,7 +290,7 @@ Common::String CharacterInfo::loadCharacterDetails(const Character &c) { RACE_NAMES[c._race], CLASS_NAMES[c._class], c.statColor(c.getStat(MIGHT), c.getStat(MIGHT, true)), c.getStat(MIGHT), c.statColor(c.getStat(ACCURACY), c.getStat(ACCURACY, true)), c.getStat(ACCURACY), - c.statColor(c._currentHp, c.getMaxHP()), + c.statColor(c._currentHp, c.getMaxHP()), c._currentHp, c.getCurrentExperience(), c.statColor(c.getStat(INTELLECT), c.getStat(INTELLECT, true)), c.getStat(INTELLECT), c.statColor(c.getStat(LUCK), c.getStat(LUCK, true)), c.getStat(LUCK), diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 3cfc56e1ec..42500ddcfe 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -187,7 +187,7 @@ int Character::getMaxSP() const { Attribute attrib; Skill skill; - if (_hasSpells) + if (!_hasSpells) return 0; if (_class == CLASS_SORCERER || _class == CLASS_ARCHER) { @@ -202,7 +202,7 @@ int Character::getMaxSP() const { for (;;) { // Get the base number of spell points - result = statBonus(getStat(attrib)); + result = statBonus(getStat(attrib)) + 3; result += RACE_SP_BONUSES[_race][attrib - 1]; if (_skills[skill]) diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 467dbe21f8..0847944147 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -304,9 +304,9 @@ const uint CLASS_EXP_LEVELS[10] = { }; const char *const CONDITION_NAMES[17] = { - nullptr, "Cursed", "Heart Broken", "Weak", "Poisoned", "Diseased", + "Cursed", "Heart Broken", "Weak", "Poisoned", "Diseased", "Insane", "In Love", "Drunk", "Asleep", "Depressed", "Confused", - "Paralyzed", "Unconscious", "Dead", "Stone", "Eradicated" + "Paralyzed", "Unconscious", "Dead", "Stone", "Eradicated", "Good" }; const int CONDITION_COLORS[17] = { diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 9c9783ba4c..bb2f356f1b 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -192,9 +192,12 @@ void Window::drawList(DrawStruct *items, int count) { if (items->_frame == -1 || items->_scale == -1 || items->_sprites == nullptr) continue; + Common::Point pt(items->_x, items->_y); + pt.x += _innerBounds.left; + pt.y += _innerBounds.top; + // TODO: There are two sprite calls in this method. Figure out why - items->_sprites->draw(*this, items->_frame, - Common::Point(items->_x, items->_y), items->_flags, items->_scale); + items->_sprites->draw(*this, items->_frame, pt, items->_flags, items->_scale); } } -- cgit v1.2.3 From 2b2ce19012c6b51e35704331d8b322f38c97f462 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 1 Feb 2015 16:51:04 -0500 Subject: XEEN: Fixes for Character Info dialog stat details display --- engines/xeen/dialogs_char_info.cpp | 15 +++++++++------ engines/xeen/party.cpp | 22 +++++++++++----------- engines/xeen/party.h | 10 +++++----- engines/xeen/town.cpp | 14 +++++++------- engines/xeen/town.h | 2 +- 5 files changed, 33 insertions(+), 30 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp index 1c0d0bfe31..44ce73e541 100644 --- a/engines/xeen/dialogs_char_info.cpp +++ b/engines/xeen/dialogs_char_info.cpp @@ -243,7 +243,7 @@ void CharacterInfo::loadDrawStructs() { * Set up the button list for the dialog */ void CharacterInfo::addButtons() { - addButton(Common::Rect(10, 24, 34, 64), 1001, &_iconSprites); + addButton(Common::Rect(10, 24, 34, 44), 1001, &_iconSprites); addButton(Common::Rect(10, 47, 34, 67), 1002, &_iconSprites); addButton(Common::Rect(10, 70, 34, 90), 1003, &_iconSprites); addButton(Common::Rect(10, 93, 34, 113), 1004, &_iconSprites); @@ -343,7 +343,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) { Common::Rect bounds(STAT_POS[0][attrib], STAT_POS[1][attrib], STAT_POS[0][attrib] + 143, STAT_POS[1][attrib] + 52); Party &party = *_vm->_party; - int stat1, stat2; + uint stat1, stat2; uint idx; Common::String msg; @@ -371,7 +371,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) { stat1 = c.getAge(false); stat2 = c.getAge(true); msg = Common::String::format(AGE_TEXT, STAT_NAMES[attrib], - stat2, c._dbDay, c._ybDay); + stat1, stat2, c._birthDay, c._birthYear); break; case 8: { @@ -422,6 +422,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) { c._poisonResistence._permanent + c.itemScan(14) + c._poisonResistence._temporary, c._energyResistence._permanent + c.itemScan(15) + c._energyResistence._temporary, c._magicResistence._permanent + c.itemScan(16) + c._magicResistence._temporary); + bounds.setHeight(80); break; case 13: { @@ -466,10 +467,10 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) { case 15: // Experience stat1 = c.getCurrentExperience(); - stat2 = c.nextExperienceLevel(); + stat2 = c.experienceToNextLevel(); msg = Common::String::format(EXPERIENCE_TEXT, STAT_NAMES[attrib], stat1, - stat2 == 0 ? ELIGIBLE : Common::String::format("%d", stat2) + stat2 == 0 ? ELIGIBLE : Common::String::format("%d", stat2).c_str() ); bounds.setHeight(43); break; @@ -478,6 +479,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) { // Gold msg = Common::String::format(IN_PARTY_IN_BANK, STAT_NAMES[attrib], party._gold, party._bankGold); + bounds.setHeight(43); break; case 17: @@ -516,6 +518,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) { Condition condition = c.worstCondition(); if (condition == NO_CONDITION) { lines[0] = Common::String::format("\n\t020%s", GOOD); + ++total; } if (party._blessed) @@ -537,7 +540,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) { lines[17].c_str(), lines[18].c_str(), lines[19].c_str() ); - bounds.top = ((total - 1) / 2) * 8; + bounds.top -= ((total - 1) / 2) * 8; bounds.setHeight(total * 9 + 26); if (bounds.bottom >= SCREEN_HEIGHT) bounds.moveTo(bounds.left, SCREEN_HEIGHT - bounds.height() - 1); diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 42500ddcfe..d046595579 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -49,7 +49,7 @@ Character::Character() { _xeenSide = 0; _class = CLASS_KNIGHT; _ACTemp = 0; - _dbDay = 0; + _birthDay = 0; _tempAge = 0; Common::fill(&_skills[0], &_skills[18], 0); Common::fill(&_awards[0], &_awards[128], false); @@ -64,7 +64,7 @@ Character::Character() { _savedMazeId = 0; _currentHp = 0; _currentSp = 0; - _ybDay = 0; + _birthYear = 0; _experience = 0; _currentAdventuringSpell = 0; _currentCombatSpell = 0; @@ -93,7 +93,7 @@ void Character::synchronize(Common::Serializer &s) { _luck.synchronize(s); s.syncAsByte(_ACTemp); _level.synchronize(s); - s.syncAsByte(_dbDay); + s.syncAsByte(_birthDay); s.syncAsByte(_tempAge); // Synchronize the skill list @@ -144,7 +144,7 @@ void Character::synchronize(Common::Serializer &s) { s.syncAsByte(_savedMazeId); s.syncAsUint16LE(_currentHp); s.syncAsUint16LE(_currentSp); - s.syncAsUint16LE(_ybDay); + s.syncAsUint16LE(_birthYear); s.syncAsUint32LE(_experience); s.syncAsByte(_currentAdventuringSpell); s.syncAsByte(_currentCombatSpell); @@ -160,7 +160,7 @@ Condition Character::worstCondition() const { } int Character::getAge(bool ignoreTemp) const { - int year = MIN(Party::_vm->_party->_year - _ybDay, 254); + int year = MIN(Party::_vm->_party->_year - _birthYear, (uint)254); return ignoreTemp ? year : year + _tempAge; } @@ -796,22 +796,22 @@ bool Character::guildMember() const { } } -uint Character::nextExperienceLevel() const { - uint base = currentExperienceLevel(); +uint Character::experienceToNextLevel() const { + uint next = nextExperienceLevel(); uint curr = getCurrentExperience(); - return (curr < base) ? 0 : curr - base; + return (curr >= next) ? 0 : next - curr; } -uint Character::currentExperienceLevel() const { +uint Character::nextExperienceLevel() const { int shift, base; if (_level._permanent >= 12) { base = _level._permanent - 12; shift = 10; } else { base = 0; - shift = _level._permanent; + shift = _level._permanent - 1; } - + return (base * 1024000) + (CLASS_EXP_LEVELS[_class] << shift); } diff --git a/engines/xeen/party.h b/engines/xeen/party.h index b793b5c696..5adc9b1c7f 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -105,7 +105,7 @@ public: AttributePair _luck; int _ACTemp; AttributePair _level; - int _dbDay; + uint _birthDay; int _tempAge; int _skills[18]; bool _awards[128]; @@ -131,7 +131,7 @@ public: int _savedMazeId; int _currentHp; int _currentSp; - int _ybDay; + uint _birthYear; uint32 _experience; int _currentAdventuringSpell; int _currentCombatSpell; @@ -173,9 +173,9 @@ public: bool guildMember() const; - uint nextExperienceLevel() const; + uint experienceToNextLevel() const; - uint currentExperienceLevel() const; + uint nextExperienceLevel() const; uint getCurrentExperience() const; @@ -223,7 +223,7 @@ public: bool _worldEnd; int _ctr24; // TODO: Figure out proper name int _day; - int _year; + uint _year; int _minutes; uint _food; int _lightCount; diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 2f31113146..3449c2e3c3 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -51,7 +51,7 @@ Town::Town(XeenEngine *vm) : _vm(vm) { _dayOfWeek = 0; _uncurseCost = 0; _flag1 = false; - _nextExperienceLevel = 0; + _experienceToNextLevel = 0; _drawCtr1 = _drawCtr2 = 0; } @@ -458,14 +458,14 @@ Common::String Town::createTownText(Character &ch) { } } - _nextExperienceLevel = ch.nextExperienceLevel(); + _experienceToNextLevel = ch.experienceToNextLevel(); - if (_nextExperienceLevel >= 0x10000 && ch._level._permanent < _v20) { + if (_experienceToNextLevel >= 0x10000 && ch._level._permanent < _v20) { int nextLevel = ch._level._permanent + 1; return Common::String::format(EXPERIENCE_FOR_LEVEL, - ch._name.c_str(), _nextExperienceLevel, nextLevel); + ch._name.c_str(), _experienceToNextLevel, nextLevel); } else if (ch._level._permanent >= 20) { - _nextExperienceLevel = 1; + _experienceToNextLevel = 1; msg = Common::String::format(LEARNED_ALL, ch._name.c_str()); } else { msg = Common::String::format(ELIGIBLE_FOR_LEVEL, @@ -906,7 +906,7 @@ Character *Town::doTrainingOptions(Character *c) { break; case Common::KEYCODE_t: - if (_nextExperienceLevel) { + if (_experienceToNextLevel) { sound.playSample(nullptr, 0); _drawFrameIndex = 0; @@ -927,7 +927,7 @@ Character *Town::doTrainingOptions(Character *c) { File f(isDarkCc ? "prtygd.voc" : "trainin2.voc"); sound.playSample(&f, 1); - c->_experience -= c->currentExperienceLevel() - + c->_experience -= c->nextExperienceLevel() - (c->getCurrentExperience() - c->_experience); c->_level._permanent++; diff --git a/engines/xeen/town.h b/engines/xeen/town.h index 807f6b5138..de87f03b23 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -58,7 +58,7 @@ private: int _arr1[6]; int _currentCharLevel; bool _flag1; - uint _nextExperienceLevel; + uint _experienceToNextLevel; int _drawFrameIndex; int _drawCtr1, _drawCtr2; -- cgit v1.2.3 From 78234db2c02c95e1b9e88b4096b9a9c96fd95adf Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 1 Feb 2015 19:04:28 -0500 Subject: XEEN: Add Quick Reference dialog --- engines/xeen/combat.cpp | 1 + engines/xeen/combat.h | 1 + engines/xeen/dialogs_char_info.cpp | 7 ++- engines/xeen/dialogs_quick_ref.cpp | 89 ++++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_quick_ref.h | 43 ++++++++++++++++++ engines/xeen/font.cpp | 10 +---- engines/xeen/interface.cpp | 6 +++ engines/xeen/module.mk | 1 + engines/xeen/party.cpp | 2 +- engines/xeen/party.h | 2 +- engines/xeen/resources.cpp | 17 +++++++- engines/xeen/resources.h | 6 ++- 12 files changed, 171 insertions(+), 14 deletions(-) create mode 100644 engines/xeen/dialogs_quick_ref.cpp create mode 100644 engines/xeen/dialogs_quick_ref.h (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 4d3cb53bf9..6237e0c5ba 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -33,6 +33,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm) { Common::fill(&_elemPow[0], &_elemPow[12], 0); Common::fill(&_elemScale[0], &_elemScale[12], 0); Common::fill(&_shooting[0], &_shooting[8], 0); + _globalCombat = 0; } void Combat::clear() { diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 550b39fd2e..c2554d5bf9 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -58,6 +58,7 @@ public: int _elemPow[12]; int _elemScale[12]; bool _shooting[8]; + int _globalCombat; public: Combat(XeenEngine *vm); diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp index 44ce73e541..985309aa8c 100644 --- a/engines/xeen/dialogs_char_info.cpp +++ b/engines/xeen/dialogs_char_info.cpp @@ -22,6 +22,7 @@ #include "xeen/dialogs_char_info.h" #include "xeen/dialogs_exchange.h" +#include "xeen/dialogs_quick_ref.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -194,6 +195,11 @@ void CharacterInfo::execute(int charIndex) { _vm->_mode = MODE_CHARACTER_INFO; break; + case Common::KEYCODE_q: + QuickReferenceDialog::show(_vm); + redrawFlag = true; + break; + case Common::KEYCODE_ESCAPE: goto exit; } @@ -568,5 +574,4 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) { return false; } - } // End of namespace Xeen diff --git a/engines/xeen/dialogs_quick_ref.cpp b/engines/xeen/dialogs_quick_ref.cpp new file mode 100644 index 0000000000..a54bb06025 --- /dev/null +++ b/engines/xeen/dialogs_quick_ref.cpp @@ -0,0 +1,89 @@ +/* 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 "xeen/dialogs_quick_ref.h" +#include "xeen/resources.h" +#include "xeen/xeen.h" + +namespace Xeen { + +void QuickReferenceDialog::show(XeenEngine *vm) { + QuickReferenceDialog *dlg = new QuickReferenceDialog(vm); + dlg->execute(); + delete dlg; +} + +void QuickReferenceDialog::execute() { + Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + Common::String lines[8]; + + events.setCursor(0); + + for (uint idx = 0; idx < (combat._globalCombat == 2 ? party._combatParty.size() : + party._partyCount); ++idx) { + Character &c = combat._globalCombat == 2 ? *party._combatParty[idx] : + party._activeParty[idx]; + Condition condition = c.worstCondition(); + lines[idx] = Common::String::format(QUICK_REF_LINE, + idx * 10 + 24, idx + 1, c._name.c_str(), + CLASS_NAMES[c._class][0], CLASS_NAMES[c._class][1], CLASS_NAMES[c._class][2], + c.statColor(c.getCurrentLevel(), c._level._permanent), c._level._permanent, + c.statColor(c._currentHp, c.getMaxHP()), c._currentHp, + c.statColor(c._currentSp, c.getMaxSP()), c._currentSp, + c.statColor(c.getArmorClass(), c.getArmorClass(true)), c.getArmorClass(), + CONDITION_COLORS[condition], + CONDITION_NAMES[condition][0], CONDITION_NAMES[condition][1], + CONDITION_NAMES[condition][2], CONDITION_NAMES[condition][3] + ); + } + + int food = (party._food / party._partyCount) / 3; + Common::String msg = Common::String::format(QUICK_REFERENCE, + lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), + lines[3].c_str(), lines[4].c_str(), lines[5].c_str(), + lines[6].c_str(), lines[7].c_str(), + party._gold, party._gems, + food, food == 1 ? "" : "s" + ); + + Window &w = screen._windows[24]; + bool windowOpen = w._enabled; + if (!windowOpen) + w.open(); + w.writeString(msg); + w.update(); + + // Wait for a key/mouse press + events.clearEvents(); + while (!_vm->shouldQuit() && !events.isKeyMousePressed()) + events.pollEventsAndWait(); + events.clearEvents(); + + if (!windowOpen) + w.close(); +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_quick_ref.h b/engines/xeen/dialogs_quick_ref.h new file mode 100644 index 0000000000..0c1b8e3f91 --- /dev/null +++ b/engines/xeen/dialogs_quick_ref.h @@ -0,0 +1,43 @@ +/* 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 XEEN_DIALOGS_QUICK_REF_H +#define XEEN_DIALOGS_QUICK_REF_H + +#include "xeen/dialogs.h" + +namespace Xeen { + +class QuickReferenceDialog : public ButtonContainer { +private: + XeenEngine *_vm; + + QuickReferenceDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + void execute(); +public: + static void show(XeenEngine *vm); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_QUICK_REF_H */ diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp index 1668ef5ae8..aca747e776 100644 --- a/engines/xeen/font.cpp +++ b/engines/xeen/font.cpp @@ -28,19 +28,13 @@ namespace Xeen { FontSurface::FontSurface() : XSurface(), _fontData(nullptr), _bgColor(DEFAULT_BG_COLOR), _fontReduced(false),_fontJustify(JUSTIFY_NONE), _msgWraps(false) { - _textColors[0] = 0; - _textColors[1] = 0x40; - _textColors[2] = 0x30; - _textColors[3] = 0x20; + setTextColor(0); } FontSurface::FontSurface(int wv, int hv) : XSurface(wv, hv), _fontData(nullptr), _msgWraps(false), _bgColor(DEFAULT_BG_COLOR), _fontReduced(false), _fontJustify(JUSTIFY_NONE) { create(w, h); - _textColors[0] = 0; - _textColors[1] = 0x40; - _textColors[2] = 0x30; - _textColors[3] = 0x20; + setTextColor(0); } /** diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index a33c726fd3..520cad5c05 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -25,6 +25,7 @@ #include "xeen/dialogs_error.h" #include "xeen/dialogs_automap.h" #include "xeen/dialogs_info.h" +#include "xeen/dialogs_quick_ref.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -704,6 +705,11 @@ void Interface::perform() { AutoMapDialog::show(_vm); break; + case Common::KEYCODE_q: + // Show the quick reference dialog + QuickReferenceDialog::show(_vm); + break; + default: break; } diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 8d3a5e52bf..eef8d78455 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -17,6 +17,7 @@ MODULE_OBJS := \ dialogs_options.o \ dialogs_info.o \ dialogs_input.o \ + dialogs_quick_ref.o \ dialogs_spells.o \ dialogs_whowill.o \ dialogs_yesno.o \ diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index d046595579..ce5ccd0bc1 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -309,7 +309,7 @@ int Character::statColor(int amount, int threshold) { return 32; } -int Character::statBonus(int statValue) const { +int Character::statBonus(uint statValue) const { int idx; for (idx = 0; STAT_VALUES[idx] <= statValue; ++idx) ; diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 5adc9b1c7f..65e6608d71 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -151,7 +151,7 @@ public: static int statColor(int amount, int threshold); - int statBonus(int statValue) const; + int statBonus(uint statValue) const; bool charSavingThrow(DamageType attackType) const; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 0847944147..eecc5b8027 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -543,9 +543,9 @@ const int AGE_RANGES_ADJUST[2][10] = { { -250, -50, -20, -10, 0, 2, 5, 10, 20, 50 } }; -const int STAT_VALUES[24] = { +const uint STAT_VALUES[24] = { 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 25, 30, 35, 40, - 50, 75, 100, 125, 150, 175, 200, 225, 250, 65535 + 50, 75, 100, 125, 150, 175, 200, 225, 250, }; const int STAT_BONUSES[24] = { @@ -971,4 +971,17 @@ const char *const FOOD_TEXT = const char *const EXCHANGE_WITH_WHOM = "\t010\v005Exchange with whom?"; +const char *const QUICK_REF_LINE = + "\xB%3d\x9""007%u)\x9""027%s\x9""110%c%c%c\x3r\x9""160\xC%02u%u\xC""d" + "\x3l\x9""170\xC%02u%d\xC""d\x9""208\xC%02u%u\xC""d\x9""247\xC" + "%02u%u\xC""d\x9""270\xC%02u%c%c%c%c\xC""d"; + +const char *const QUICK_REFERENCE = + "\xD\x3""cQuick Reference Chart\xB""012\x3l" + "\x9""007#\x9""027Name\x9""110Cls\x9""140Lvl\x9""176H.P." + "\x9""212S.P.\x9""241A.C.\x9""270Cond" + "%s%s%s%s%s%s%s%s" + "\xB""110\x9""064\x3""cGold\x9""144Gems\x9""224Food\xB""119" + "\x9""064\xC""15%lu\x9""144%lu\x9""224%u day%s\xC""d"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 64387e7f54..e8f5c31867 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -147,7 +147,7 @@ extern const int AGE_RANGES[10]; extern const int AGE_RANGES_ADJUST[2][10]; -extern const int STAT_VALUES[24]; +extern const uint STAT_VALUES[24]; extern const int STAT_BONUSES[24]; @@ -323,6 +323,10 @@ extern const char *const FOOD_TEXT; extern const char *const EXCHANGE_WITH_WHOM; +extern const char *const QUICK_REF_LINE; + +extern const char *const QUICK_REFERENCE; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From 7febe773008db7cee0ed1b3f5f1f2fb114d22334 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 1 Feb 2015 23:32:16 -0500 Subject: XEEN: Beginnings of Items dialog --- engines/xeen/dialogs_char_info.cpp | 3 +- engines/xeen/dialogs_items.cpp | 292 +++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_items.h | 63 ++++++++ engines/xeen/dialogs_quick_ref.cpp | 1 - engines/xeen/items.cpp | 6 +- engines/xeen/items.h | 4 +- engines/xeen/module.mk | 1 + engines/xeen/party.cpp | 18 +-- engines/xeen/party.h | 12 +- engines/xeen/resources.cpp | 25 ++++ engines/xeen/resources.h | 19 +++ engines/xeen/scripts.cpp | 12 +- engines/xeen/town.cpp | 9 +- engines/xeen/town.h | 2 - 14 files changed, 429 insertions(+), 38 deletions(-) create mode 100644 engines/xeen/dialogs_items.cpp create mode 100644 engines/xeen/dialogs_items.h (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp index 985309aa8c..1d907cf7d9 100644 --- a/engines/xeen/dialogs_char_info.cpp +++ b/engines/xeen/dialogs_char_info.cpp @@ -22,6 +22,7 @@ #include "xeen/dialogs_char_info.h" #include "xeen/dialogs_exchange.h" +#include "xeen/dialogs_items.h" #include "xeen/dialogs_quick_ref.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -185,7 +186,7 @@ void CharacterInfo::execute(int charIndex) { case Common::KEYCODE_i: _vm->_mode = oldMode; _vm->_treasure._v1 = _vm->_mode == MODE_InCombat; - error("TODO: c = ItemDialog::show"); + c = ItemsDialog::show(_vm, c, ITEMMODE_CHAR_INFO); if (!c) { party._stepped = true; diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp new file mode 100644 index 0000000000..fea043213f --- /dev/null +++ b/engines/xeen/dialogs_items.cpp @@ -0,0 +1,292 @@ +/* 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 "xeen/dialogs_items.h" +#include "xeen/resources.h" +#include "xeen/xeen.h" + +namespace Xeen { + +Character *ItemsDialog::show(XeenEngine *vm, Character *c, ItemsMode mode) { + ItemsDialog *dlg = new ItemsDialog(vm); + Character *result = dlg->execute(c, mode); + delete dlg; + + return result; +} + +Character *ItemsDialog::execute(Character *c, ItemsMode mode) { + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + + Character *tempChar = c; + int typeNum = mode == ITEMMODE_4 || mode == ITEMMODE_COMBAT ? 3 : 0; + int varA = mode == ITEMMODE_COMBAT ? 1 : 0; + if (varA != 0) + mode = ITEMMODE_CHAR_INFO; + int varE = mode == 1 ? 1 : 0; + + events.setCursor(0); + loadButtons(mode, c); + + screen._windows[29].open(); + screen._windows[30].open(); + + bool redrawFlag = true; + while (!_vm->shouldQuit()) { + if (redrawFlag) { + if ((mode != ITEMMODE_CHAR_INFO || typeNum != 3) && mode != ITEMMODE_6 + && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) { + _buttons[8]._bounds.moveTo(148, _buttons[8]._bounds.top); + _buttons[9]._draw = false; + } else if (mode == ITEMMODE_4) { + _buttons[4]._value = Common::KEYCODE_r; + } else if (mode == ITEMMODE_6) { + _buttons[4]._value = Common::KEYCODE_e; + } else if (mode == ITEMMODE_TO_GOLD) { + _buttons[4]._value = Common::KEYCODE_g; + } else { + _buttons[8]._bounds.moveTo(0, _buttons[8]._bounds.top); + _buttons[9]._draw = true; + _buttons[9]._value = Common::KEYCODE_u; + } + + // Write text for the dialog + Common::String msg; + if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_8 && mode != ITEMMODE_6 + && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) { + msg = Common::String::format(ITEMS_DIALOG_TEXT1, + BTN_SELL, BTN_IDENTIFY, BTN_FIX); + } else if (mode != ITEMMODE_6 && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) { + msg = Common::String::format(ITEMS_DIALOG_TEXT1, + typeNum == 3 ? BTN_USE : BTN_EQUIP, + BTN_REMOVE, BTN_DISCARD, BTN_QUEST); + } else if (mode == ITEMMODE_6) { + msg = Common::String::format(ITEMS_DIALOG_TEXT2, BTN_ENCHANT); + } else if (mode == ITEMMODE_4) { + msg = Common::String::format(ITEMS_DIALOG_TEXT2, BTN_RECHARGE); + } else { + msg = Common::String::format(ITEMS_DIALOG_TEXT2, BTN_GOLD); + } + + screen._windows[29].writeString(msg); + drawButtons(&screen); + } + + int arr[40]; + Common::fill(&arr[0], &arr[40], false); + int var2 = -1; + + if (mode == ITEMMODE_CHAR_INFO || typeNum != 3) { + _iconSprites.draw(screen, 8, Common::Point(148, 109)); + } + if (mode != ITEMMODE_6 && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) { + _iconSprites.draw(screen, 10, Common::Point(182, 109)); + _iconSprites.draw(screen, 12, Common::Point(216, 109)); + _iconSprites.draw(screen, 14, Common::Point(250, 109)); + } + + switch (mode) { + case ITEMMODE_CHAR_INFO: + _iconSprites.draw(screen, 9, Common::Point(148, 109)); + break; + case ITEMMODE_BLACKSMITH: + _iconSprites.draw(screen, 11, Common::Point(182, 109)); + break; + case ITEMMODE_9: + _iconSprites.draw(screen, 15, Common::Point(250, 109)); + break; + case ITEMMODE_10: + _iconSprites.draw(screen, 13, Common::Point(216, 109)); + break; + default: + break; + } + + for (int idx = 0; idx < 9; ++idx) { + _itemsDrawList[idx]._y = 10 + idx * 9; + + switch (typeNum) { + case 0: + if (c->_weapons[idx]._id) { + if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8 + || mode == ITEMMODE_6 || mode == ITEMMODE_4) { + // TODO + } + } else if (_itemsDrawList[idx]._sprites == nullptr) { + // TODO + } + break; + // TODO + default: + break; + } + } + } + + return c; +} + +/** + * Load the buttons for the dialog + */ +void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) { + _iconSprites.load(Common::String::format("%s.icn", + (mode == ITEMMODE_CHAR_INFO) ? "items" : "buy")); + _equipSprites.load("equip.icn"); + + if (mode == ITEMMODE_6 || mode == ITEMMODE_4 || mode == ITEMMODE_TO_GOLD) { + // Enchant button list + addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_w, &_iconSprites); + addButton(Common::Rect(46, 109, 70, 129), Common::KEYCODE_a, &_iconSprites); + addButton(Common::Rect(80, 109, 104, 129), Common::KEYCODE_c, &_iconSprites); + addButton(Common::Rect(114, 109, 138, 129), Common::KEYCODE_n, &_iconSprites); + addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_e, &_iconSprites); + addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites); + addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_u, &_iconSprites); + addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1, &_iconSprites, false); + addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2, &_iconSprites, false); + addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3, &_iconSprites, false); + addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4, &_iconSprites, false); + addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5, &_iconSprites, false); + addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6, &_iconSprites, false); + addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, &_iconSprites, false); + addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, &_iconSprites, false); + addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, &_iconSprites, false); + } else { + addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_w, &_iconSprites); + addButton(Common::Rect(46, 109, 70, 129), Common::KEYCODE_a, &_iconSprites); + addButton(Common::Rect(80, 109, 104, 129), Common::KEYCODE_c, &_iconSprites); + addButton(Common::Rect(114, 109, 138, 129), Common::KEYCODE_n, &_iconSprites); + addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_e, &_iconSprites); + addButton(Common::Rect(182, 109, 206, 129), Common::KEYCODE_r, &_iconSprites); + addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_d, &_iconSprites); + addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_q, &_iconSprites); + addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites); + addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1, &_iconSprites, false); + addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2, &_iconSprites, false); + addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3, &_iconSprites, false); + addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4, &_iconSprites, false); + addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5, &_iconSprites, false); + addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6, &_iconSprites, false); + addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, &_iconSprites, false); + addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, &_iconSprites, false); + addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, &_iconSprites, false); + } + + if (mode == ITEMMODE_BLACKSMITH) { + _oldCharacter = c; + c = &_itemsCharacter; + blackData2CharData(); + + _buttons[4]._value = Common::KEYCODE_b; + _buttons[5]._value = Common::KEYCODE_s; + _buttons[6]._value = Common::KEYCODE_i; + _buttons[7]._value = Common::KEYCODE_f; + + setEquipmentIcons(); + } else { + _buttons[4]._value = Common::KEYCODE_e; + _buttons[5]._value = Common::KEYCODE_r; + _buttons[6]._value = Common::KEYCODE_d; + _buttons[7]._value = Common::KEYCODE_q; + } +} + +/** + * Loads the temporary _itemsCharacter character with the item set + * the given blacksmith has available, so the user can "view" the + * set as if it were a standard character's inventory + */ +void ItemsDialog::blackData2CharData() { + Party &party = *_vm->_party; + bool isDarkCc = _vm->_files->_isDarkCc; + int slotIndex = 0; + while (party._mazeId != (int)BLACKSMITH_MAP_IDS[isDarkCc][slotIndex] && slotIndex < 4) + ++slotIndex; + if (slotIndex == 4) + slotIndex = 0; + + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + _itemsCharacter._weapons[idx] = party._blacksmithWeapons[isDarkCc][idx]; + _itemsCharacter._armor[idx] = party._blacksmithArmor[isDarkCc][idx]; + _itemsCharacter._accessories[idx] = party._blacksmithAccessories[isDarkCc][idx]; + _itemsCharacter._misc[idx] = party._blacksmithMisc[isDarkCc][idx]; + } +} + +/** + * Sets the equipment icon to use for each item for display + */ +void ItemsDialog::setEquipmentIcons() { + for (int typeIndex = 0; typeIndex < 4; ++typeIndex) { + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + switch (typeIndex) { + case 0: { + XeenItem &i = _itemsCharacter._weapons[idx]; + if (i._id <= 17) + i._equipped = 1; + else if (i._id <= 29 || i._id > 33) + i._equipped = 13; + else + i._equipped = 4; + break; + } + + case 1: { + XeenItem &i = _itemsCharacter._armor[idx]; + if (i._id <= 7) + i._equipped = 3; + else if (i._id == 9) + i._equipped = 5; + else if (i._id == 10) + i._equipped = 9; + else if (i._id <= 12) + i._equipped = 10; + else + i._equipped = 6; + break; + } + + case 2: { + XeenItem &i = _itemsCharacter._accessories[idx]; + if (i._id == 1) + i._id = 8; + else if (i._id == 2) + i._equipped = 12; + else if (i._id <= 7) + i._equipped = 7; + else + i._equipped = 11; + break; + } + + default: + break; + } + } + } +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h new file mode 100644 index 0000000000..100ac5c8b7 --- /dev/null +++ b/engines/xeen/dialogs_items.h @@ -0,0 +1,63 @@ +/* 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 XEEN_DIALOGS_ITEMS_H +#define XEEN_DIALOGS_ITEMS_H + +#include "xeen/dialogs.h" +#include "xeen/party.h" +#include "xeen/screen.h" + +namespace Xeen { + +enum ItemsMode { + ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_4 = 4, + ITEMMODE_6 = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, + ITEMMODE_9 = 9, ITEMMODE_10 = 10, ITEMMODE_TO_GOLD = 11 +}; + +class ItemsDialog : public ButtonContainer { +private: + XeenEngine *_vm; + SpriteResource _iconSprites; + SpriteResource _equipSprites; + Character _itemsCharacter; + Character *_oldCharacter; + DrawStruct _itemsDrawList[9]; + + ItemsDialog(XeenEngine *vm) : ButtonContainer(), + _vm(vm), _oldCharacter(nullptr) {} + + Character *execute(Character *c, ItemsMode mode); + + void loadButtons(ItemsMode mode, Character *&c); + + void blackData2CharData(); + + void setEquipmentIcons(); +public: + static Character *show(XeenEngine *vm, Character *c, ItemsMode mode); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_ITEMS_H */ diff --git a/engines/xeen/dialogs_quick_ref.cpp b/engines/xeen/dialogs_quick_ref.cpp index a54bb06025..6c8da5ef86 100644 --- a/engines/xeen/dialogs_quick_ref.cpp +++ b/engines/xeen/dialogs_quick_ref.cpp @@ -35,7 +35,6 @@ void QuickReferenceDialog::show(XeenEngine *vm) { void QuickReferenceDialog::execute() { Combat &combat = *_vm->_combat; EventsManager &events = *_vm->_events; - Interface &intf = *_vm->_interface; Party &party = *_vm->_party; Screen &screen = *_vm->_screen; Common::String lines[8]; diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp index c55a227502..fd06af1024 100644 --- a/engines/xeen/items.cpp +++ b/engines/xeen/items.cpp @@ -26,13 +26,13 @@ namespace Xeen { XeenItem::XeenItem() { - _material = _name = _bonusFlags = 0; - _equipped = false; + _material = _id = _bonusFlags = 0; + _equipped = 0; } void XeenItem::synchronize(Common::Serializer &s) { s.syncAsByte(_material); - s.syncAsByte(_name); + s.syncAsByte(_id); s.syncAsByte(_bonusFlags); s.syncAsByte(_equipped); } diff --git a/engines/xeen/items.h b/engines/xeen/items.h index 8e8f172790..154fd21888 100644 --- a/engines/xeen/items.h +++ b/engines/xeen/items.h @@ -35,9 +35,9 @@ enum BonusFlags { FLAG_CURSED = 0x40 }; class XeenItem { public: int _material; - uint _name; + uint _id; int _bonusFlags; - bool _equipped; + int _equipped; public: XeenItem(); diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index eef8d78455..c1cdd055b8 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -17,6 +17,7 @@ MODULE_OBJS := \ dialogs_options.o \ dialogs_info.o \ dialogs_input.o \ + dialogs_items.o \ dialogs_quick_ref.o \ dialogs_spells.o \ dialogs_whowill.o \ diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index ce5ccd0bc1..03535066e1 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -487,7 +487,7 @@ int Character::itemScan(int itemId) const { } if (itemId == 9) { - result += ARMOR_STRENGTHS[item._name]; + result += ARMOR_STRENGTHS[item._id]; if (item._material >= 37 && item._material <= 58) result += METAL_LAC[item._material - 37]; @@ -959,13 +959,13 @@ void Party::synchronize(Common::Serializer &s) { s.syncAsByte(_difficulty); for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithWeapons[i].synchronize(s); + _blacksmithWeapons[0][i].synchronize(s); for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithArmor[i].synchronize(s); + _blacksmithArmor[0][i].synchronize(s); for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithAccessories[i].synchronize(s); + _blacksmithAccessories[0][i].synchronize(s); for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithMisc[i].synchronize(s); + _blacksmithMisc[0][i].synchronize(s); s.syncAsUint16LE(_cloudsEnd); s.syncAsUint16LE(_darkSideEnd); @@ -998,13 +998,13 @@ void Party::synchronize(Common::Serializer &s) { s.syncAsByte(_questItems[i]); for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithWeapons2[i].synchronize(s); + _blacksmithWeapons[1][i].synchronize(s); for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithArmor2[i].synchronize(s); + _blacksmithArmor[1][i].synchronize(s); for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithAccessories2[i].synchronize(s); + _blacksmithAccessories[1][i].synchronize(s); for (int i = 0; i < ITEMS_COUNT; ++i) - _blacksmithMisc2[i].synchronize(s); + _blacksmithMisc[1][i].synchronize(s); for (int i = 0; i < TOTAL_CHARACTERS; ++i) SavesManager::syncBitFlags(s, &_characterFlags[i][0], &_characterFlags[i][24]); diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 65e6608d71..8285ddfecf 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -214,10 +214,10 @@ public: int _holyBonus; int _heroism; Difficulty _difficulty; - XeenItem _blacksmithWeapons[ITEMS_COUNT]; - XeenItem _blacksmithArmor[ITEMS_COUNT]; - XeenItem _blacksmithAccessories[ITEMS_COUNT]; - XeenItem _blacksmithMisc[ITEMS_COUNT]; + XeenItem _blacksmithWeapons[2][ITEMS_COUNT]; + XeenItem _blacksmithArmor[2][ITEMS_COUNT]; + XeenItem _blacksmithAccessories[2][ITEMS_COUNT]; + XeenItem _blacksmithMisc[2][ITEMS_COUNT]; bool _cloudsEnd; bool _darkSideEnd; bool _worldEnd; @@ -245,10 +245,6 @@ public: bool _worldFlags[128]; bool _quests[64]; int _questItems[85]; - XeenItem _blacksmithWeapons2[ITEMS_COUNT]; - XeenItem _blacksmithArmor2[ITEMS_COUNT]; - XeenItem _blacksmithAccessories2[ITEMS_COUNT]; - XeenItem _blacksmithMisc2[ITEMS_COUNT]; bool _characterFlags[30][24]; public: // Other party related runtime data diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index eecc5b8027..d89d2e6e25 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -984,4 +984,29 @@ const char *const QUICK_REFERENCE = "\xB""110\x9""064\x3""cGold\x9""144Gems\x9""224Food\xB""119" "\x9""064\xC""15%lu\x9""144%lu\x9""224%u day%s\xC""d"; +const uint BLACKSMITH_MAP_IDS[2][4] = { { 28, 30, 73, 49 }, { 29, 31, 37, 43 } }; + +char *const ITEMS_DIALOG_TEXT1 = + "\r\x2\x3""c\v021\t017\f37W\fdeap\t051\f37A\fdrmor\t085A" + "\f37c\fdces\t119\f37M\fdisc\t153%s\t187%s\t221%s" + "\t255%s\t289Exit"; + +char *const ITEMS_DIALOG_TEXT2 = + "\r\x2\x3""c\v021\t017\f37W\fdeap\t051\f37A\fdrmor\t085A" + "\f37c\fdces\t119\f37M\fdisc\t153\f37%s\t289Exit"; + +const char *const BTN_BUY = "\f37B\fduy"; +const char *const BTN_SELL = "\f37S\fdell"; +const char *const BTN_IDENTIFY = "\f37I\fddentify"; +const char *const BTN_FIX = "\f37F\fdix"; +const char *const BTN_USE = "\f37U\fdse"; +const char *const BTN_EQUIP = "\f37E\fdquip"; +const char *const BTN_REMOVE = "\f37R\fdem"; +const char *const BTN_DISCARD = "\f37D\fdisc"; +const char *const BTN_QUEST = "\f37Q\fduest"; +const char *const BTN_ENCHANT = "E\fdnchant"; +const char *const BTN_RECHARGE = "R\fdechrg"; +const char *const BTN_GOLD = "G\fdold"; + + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index e8f5c31867..5437d40641 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -327,6 +327,25 @@ extern const char *const QUICK_REF_LINE; extern const char *const QUICK_REFERENCE; +extern const uint BLACKSMITH_MAP_IDS[2][4]; + +extern char *const ITEMS_DIALOG_TEXT1; +extern char *const ITEMS_DIALOG_TEXT2; + +extern const char *const BTN_BUY; +extern const char *const BTN_SELL; +extern const char *const BTN_IDENTIFY; +extern const char *const BTN_FIX; +extern const char *const BTN_USE; +extern const char *const BTN_EQUIP; +extern const char *const BTN_REMOVE; +extern const char *const BTN_DISCARD; +extern const char *const BTN_EQUIP; +extern const char *const BTN_QUEST; +extern const char *const BTN_ENCHANT; +extern const char *const BTN_RECHARGE; +extern const char *const BTN_GOLD; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 3ba6329b70..12fe2f1257 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -623,8 +623,8 @@ void Scripts::cmdConfirmWord(Common::Array<byte> ¶ms) { if (result == 59 && !_vm->_files->_isDarkCc) { for (int idx = 0; idx < TOTAL_ITEMS; ++idx) { XeenItem &item = _vm->_treasure._weapons[idx]; - if (!item._name) { - item._name = 34; + if (!item._id) { + item._id = 34; item._material = 0; item._bonusFlags = 0; _vm->_treasure._hasItems = true; @@ -1007,22 +1007,22 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { if (mask < 82) { for (int idx = 0; idx < 9; ++idx) { if (mask == 35) { - if (ps._weapons[idx]._name == mask) { + if (ps._weapons[idx]._id == mask) { v = mask; break; } } else if (mask < 49) { - if (ps._armor[idx]._name == (mask - 35)) { + if (ps._armor[idx]._id == (mask - 35)) { v = mask; break; } } else if (mask < 60) { - if (ps._accessories[idx]._name == (mask - 49)) { + if (ps._accessories[idx]._id == (mask - 49)) { v = mask; break; } } else { - if (ps._misc[idx]._name == (mask - 60)) { + if (ps._misc[idx]._id == (mask - 60)) { v = mask; break; } diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 3449c2e3c3..c5cf0b6a10 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -22,6 +22,7 @@ #include "xeen/town.h" #include "xeen/dialogs_input.h" +#include "xeen/dialogs_items.h" #include "xeen/dialogs_yesno.h" #include "xeen/dialogs_spells.h" #include "xeen/resources.h" @@ -536,8 +537,8 @@ Character *Town::doBlacksmithOptions(Character *c) { intf.highlightChar(_buttonValue); } } - else if (_buttonValue == Common::KEYCODE_c) { - c = showItems(c, 1); + else if (_buttonValue == Common::KEYCODE_b) { + c = ItemsDialog::show(_vm, c, ITEMMODE_BLACKSMITH); _buttonValue = 0; } @@ -1190,8 +1191,4 @@ bool Town::isActive() const { return _townSprites.size() > 0 && !_townSprites[0].empty(); } -Character *Town::showItems(Character *c, int v2) { - error("TODO: showItems"); -} - } // End of namespace Xeen diff --git a/engines/xeen/town.h b/engines/xeen/town.h index de87f03b23..8f6ef15710 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -95,8 +95,6 @@ private: Character *doTrainingOptions(Character *c); void depositWithdrawl(int choice); - - Character *showItems(Character *c, int v2); public: Town(XeenEngine *vm); -- cgit v1.2.3 From 2b8303c0d8b54ee5251296c86a320735422b62e2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 2 Feb 2015 18:20:27 -0500 Subject: XEEN: Implemented assembleItemName method --- engines/xeen/items.h | 4 ++- engines/xeen/party.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/party.h | 2 ++ engines/xeen/resources.cpp | 32 +++++++++++++++++++++++ engines/xeen/resources.h | 8 ++++++ engines/xeen/town.cpp | 8 +++--- 6 files changed, 113 insertions(+), 5 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/items.h b/engines/xeen/items.h index 154fd21888..943b1876c2 100644 --- a/engines/xeen/items.h +++ b/engines/xeen/items.h @@ -30,7 +30,9 @@ namespace Xeen { #define TOTAL_ITEMS 10 -enum BonusFlags { FLAG_CURSED = 0x40 }; +enum BonusFlags { + ITEMFLAG_BONUS_MASK = 0xBF, ITEMFLAG_CURSED = 0x40, ITEMFLAG_BROKEN = 0x80 +}; class XeenItem { public: diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 03535066e1..210852686a 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -855,6 +855,70 @@ int Character::getNumAwards() const { return total; } +/** + * Assembles a full lines description for a specified item for use in + * the Items dialog + */ +Common::String Character::assembleItemName(int itemIndex, int displayNum, int typeNum) { + Spells &spells = *Party::_vm->_spells; + + switch (typeNum) { + case 0: { + // Weapons + XeenItem &i = _weapons[itemIndex]; + return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum, + !i._bonusFlags ? spells._maeNames[i._material] : "", + (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", + (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + WEAPON_NAMES[i._id], + !i._bonusFlags ? "" : BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK], + (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || + !i._bonusFlags ? "\b " : "" + ); + } + + case 1: { + // Armor + XeenItem &i = _armor[itemIndex]; + return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, + !i._bonusFlags ? "" : spells._maeNames[i._material], + (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", + (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + ARMOR_NAMES[i._id], + (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || + !i._bonusFlags ? "\b " : "" + ); + } + + case 2: { + // Accessories + XeenItem &i = _accessories[itemIndex]; + return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, + !i._bonusFlags ? "" : spells._maeNames[i._material], + (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", + (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + ARMOR_NAMES[i._id], + (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || + !i._bonusFlags ? "\b " : "" + ); + } + + case 3: { + // Misc + XeenItem &i = _misc[itemIndex]; + return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, + !i._bonusFlags ? "" : spells._maeNames[i._material], + (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", + (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + ARMOR_NAMES[i._id], + (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || + !i._id ? "\b " : "" + ); + } + default: + return ""; + } +} /*------------------------------------------------------------------------*/ diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 8285ddfecf..d719320766 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -182,6 +182,8 @@ public: int getNumSkills() const; int getNumAwards() const; + + Common::String assembleItemName(int itemIndex, int displayNum, int typeNum); }; class Roster: public Common::Array<Character> { diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index d89d2e6e25..89f6c8a5e5 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1008,5 +1008,37 @@ const char *const BTN_ENCHANT = "E\fdnchant"; const char *const BTN_RECHARGE = "R\fdechrg"; const char *const BTN_GOLD = "G\fdold"; +const char *const ITEM_BROKEN = "\f32broken "; +const char *const ITEM_CURSED = "\f09cursed "; +const char *const BONUS_NAMES[7] = { + "", "Dragon Slayer", "Undead Eater", "Golem Smasher", + "Bug Zapper", "Monster Masher", "Beast Bopper" +}; +const char *const WEAPON_NAMES[35] = { + nullptr, "long sword ", "short sword ", "broad sword ", "scimitar ", + "cutlass ", "sabre ", "club ", "hand axe ", "katana ", "nunchakas ", + "wakazashi ", "dagger ", "mace ", "flail ", "cudgel ", "maul ", "spear ", + "bardiche ", "glaive ", "halberd ", "pike ", "flamberge ", "trident ", + "staff ", "hammer ", "naginata ", "battle axe ", "grand axe ", "great axe ", + "short bow ", "long bow ", "crossbow ", "sling ", "Xeen Slayer Sword" +}; + +const char *const ARMOR_NAMES[14] = { + nullptr, "Robes ", "Scale rmor ", "ring mail ", "chain mail ", + "splint mail ", "plate mail ", "plate armor ", "shield ", + "helm ", "boots ", "cloak ", "cape ", "gauntlets " +}; + +const char *const ACCESSORY_NAMES[11] = { + nullptr, "ring ", "belt ", "broach ", "medal ", "charm ", "cameo ", + "scarab ", "pendant ", "necklace ", "amulet " +}; + +const char *const MISC_NAMES[22] = { + nullptr, "rod ", "jewel ", "gem ", "box ", "orb ", "horn ", "coin ", + "wand ", "whistle ", "potion ", "scroll ", "RogueVM", + "bogus", "bogus", "bogus", "bogus", "bogus", + "bogus", "bogus", "bogus", "bogus" +}; } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 5437d40641..4b08615520 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -346,6 +346,14 @@ extern const char *const BTN_ENCHANT; extern const char *const BTN_RECHARGE; extern const char *const BTN_GOLD; +extern const char *const ITEM_BROKEN; +extern const char *const ITEM_CURSED; +extern const char *const BONUS_NAMES[7]; +extern const char *const WEAPON_NAMES[35]; +extern const char *const ARMOR_NAMES[14]; +extern const char *const ACCESSORY_NAMES[11]; +extern const char *const MISC_NAMES[22]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index c5cf0b6a10..3df26859d4 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -863,10 +863,10 @@ Character *Town::doTempleOptions(Character *c) { case Common::KEYCODE_u: if (_uncurseCost && party.subtract(0, _uncurseCost, 0, WT_2)) { for (int idx = 0; idx < 9; ++idx) { - c->_weapons[idx]._bonusFlags &= ~FLAG_CURSED; - c->_armor[idx]._bonusFlags &= ~FLAG_CURSED; - c->_accessories[idx]._bonusFlags &= ~FLAG_CURSED; - c->_misc[idx]._bonusFlags &= ~FLAG_CURSED; + c->_weapons[idx]._bonusFlags &= ~ITEMFLAG_CURSED; + c->_armor[idx]._bonusFlags &= ~ITEMFLAG_CURSED; + c->_accessories[idx]._bonusFlags &= ~ITEMFLAG_CURSED; + c->_misc[idx]._bonusFlags &= ~ITEMFLAG_CURSED; } _v1 = 1440; -- cgit v1.2.3 From 3767f316195940bbe02a3f10e7139f0267197ce8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 2 Feb 2015 21:29:58 -0500 Subject: XEEN: Implemented calcItemCost --- engines/xeen/dialogs_items.cpp | 125 ++++++++++++++++++++++++++++++++++++++++- engines/xeen/dialogs_items.h | 6 +- engines/xeen/resources.cpp | 39 +++++++++++-- engines/xeen/resources.h | 14 ++++- 4 files changed, 174 insertions(+), 10 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index fea043213f..67778777eb 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -94,8 +94,9 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { drawButtons(&screen); } + Common::StringArray lines; int arr[40]; - Common::fill(&arr[0], &arr[40], false); + Common::fill(&arr[0], &arr[40], 0); int var2 = -1; if (mode == ITEMMODE_CHAR_INFO || typeNum != 3) { @@ -132,8 +133,20 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { if (c->_weapons[idx]._id) { if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8 || mode == ITEMMODE_6 || mode == ITEMMODE_4) { - // TODO + lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, + arr[idx], idx + 1, + c->assembleItemName(idx, arr[idx], typeNum))); + } else { + lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2, + arr[idx], idx + 1, + c->assembleItemName(idx, arr[idx], typeNum), + calcItemCost(c, idx, mode, + mode == ITEMMODE_TO_GOLD ? 1 : c->_skills[MERCHANT], + typeNum) + )); } + + // TODO } else if (_itemsDrawList[idx]._sprites == nullptr) { // TODO } @@ -289,4 +302,112 @@ void ItemsDialog::setEquipmentIcons() { } } +/** + * Calculate the cost of an item + */ +int ItemsDialog::calcItemCost(Character *c, int itemIndex, int mode, + int skillLevel, int typeNum) { + int amount1 = 0, amount2 = 0, amount3 = 0, amount4 = 0; + int result = 0; + int level = skillLevel & 0x7f; + + switch (mode) { + case ITEMMODE_BLACKSMITH: + level = 0; + break; + case ITEMMODE_2: + case ITEMMODE_TO_GOLD: + level = level == 0 ? 1 : 0; + break; + case ITEMMODE_10: + level = 2; + break; + case ITEMMODE_9: + level = 3; + break; + default: + break; + } + + switch (typeNum) { + case 0: + case 1: + case 2: { + // 0=Weapons, 1=Armor, 2=Accessories + XeenItem &i = (mode == 0) ? c->_weapons[itemIndex] : + (mode == 1 ? c->_armor[itemIndex] : c->_accessories[itemIndex]); + amount1 = (mode == 0) ? WEAPON_BASE_COSTS[i._id] : + (mode == 1 ? ARMOR_BASE_COSTS[i._id] : ACCESSORY_BASE_COSTS[i._id]); + + if (i._material > 36 && i._material < 59) { + switch (i._material) { + case 37: + amount1 /= 10; + break; + case 38: + amount1 /= 4; + break; + case 39: + amount1 /= 2; + break; + case 40: + amount1 /= 4; + break; + default: + amount1 *= METAL_BASE_MULTIPLIERS[i._material - 37]; + break; + } + } + + if (i._material < 37) + amount2 = ELEMENTAL_DAMAGE[i._material] * 100; + else if (i._material > 58) + amount3 = METAL_BASE_MULTIPLIERS[i._material] * 100; + + switch (mode) { + case ITEMMODE_BLACKSMITH: + case ITEMMODE_2: + case ITEMMODE_9: + case ITEMMODE_10: + case ITEMMODE_TO_GOLD: + result = (amount1 + amount2 + amount3 + amount4) / ITEM_SKILL_DIVISORS[level]; + if (!result) + result = 1; + break; + default: + break; + } + break; + } + + case 3: { + // Misc + XeenItem &i = c->_misc[itemIndex]; + amount1 = MISC_MATERIAL_COSTS[i._material]; + amount4 = MISC_BASE_COSTS[i._id]; + + switch (mode) { + case ITEMMODE_BLACKSMITH: + case ITEMMODE_2: + case ITEMMODE_9: + case ITEMMODE_10: + case ITEMMODE_TO_GOLD: + result = (amount1 + amount2 + amount3 + amount4) / ITEM_SKILL_DIVISORS[level]; + if (!result) + result = 1; + break; + default: + break; + } + break; + } + + default: + break; + } + + return (mode == ITEMMODE_CHAR_INFO) ? 0 : result; +} + + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h index 100ac5c8b7..1259b2524f 100644 --- a/engines/xeen/dialogs_items.h +++ b/engines/xeen/dialogs_items.h @@ -30,8 +30,8 @@ namespace Xeen { enum ItemsMode { - ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_4 = 4, - ITEMMODE_6 = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, + ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_2 = 2, + ITEMMODE_4 = 4, ITEMMODE_6 = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, ITEMMODE_9 = 9, ITEMMODE_10 = 10, ITEMMODE_TO_GOLD = 11 }; @@ -54,6 +54,8 @@ private: void blackData2CharData(); void setEquipmentIcons(); + + int calcItemCost(Character *c, int itemIndex, int mode, int skillLevel, int typeNum); public: static Character *show(XeenEngine *vm, Character *c, ItemsMode mode); }; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 89f6c8a5e5..b856baab47 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -986,14 +986,15 @@ const char *const QUICK_REFERENCE = const uint BLACKSMITH_MAP_IDS[2][4] = { { 28, 30, 73, 49 }, { 29, 31, 37, 43 } }; -char *const ITEMS_DIALOG_TEXT1 = +const char *const ITEMS_DIALOG_TEXT1 = "\r\x2\x3""c\v021\t017\f37W\fdeap\t051\f37A\fdrmor\t085A" "\f37c\fdces\t119\f37M\fdisc\t153%s\t187%s\t221%s" "\t255%s\t289Exit"; - -char *const ITEMS_DIALOG_TEXT2 = +const char *const ITEMS_DIALOG_TEXT2 = "\r\x2\x3""c\v021\t017\f37W\fdeap\t051\f37A\fdrmor\t085A" "\f37c\fdces\t119\f37M\fdisc\t153\f37%s\t289Exit"; +const char *const ITEMS_DIALOG_LINE1 = "\x3r\f%02u\f023%2d)\x3l\t028%s\n"; +const char *const ITEMS_DIALOG_LINE2 = "\x3r\f%02u\t023%2d)\x3l\t028%s\x3r\t000%lu\n"; const char *const BTN_BUY = "\f37B\fduy"; const char *const BTN_SELL = "\f37S\fdell"; @@ -1037,8 +1038,38 @@ const char *const ACCESSORY_NAMES[11] = { const char *const MISC_NAMES[22] = { nullptr, "rod ", "jewel ", "gem ", "box ", "orb ", "horn ", "coin ", "wand ", "whistle ", "potion ", "scroll ", "RogueVM", - "bogus", "bogus", "bogus", "bogus", "bogus", + "bogusg", "bogus", "bogus", "bogus", "bogus", "bogus", "bogus", "bogus", "bogus" }; +const int WEAPON_BASE_COSTS[35] = { + 0, 50, 15, 100, 80, 40, 60, 1, 10, 150, 30, 60, 8, 50, + 100, 15, 30, 15, 200, 80, 250, 150, 400, 100, 40, 120, + 300, 100, 200, 300, 25, 100, 50, 15, 0 +}; +const int ARMOR_BASE_COSTS[25] = { + 0, 20, 100, 200, 400, 600, 1000, 2000, 100, 60, 40, 250, 200, 100 +}; +const int ACCESSORY_BASE_COSTS[11] = { + 0, 100, 100, 250, 100, 50, 300, 200, 500, 1000, 2000 +}; +const int MISC_MATERIAL_COSTS[22] = { + 0, 50, 1000, 500, 10, 100, 20, 10, 50, 10, 10, 100, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; +const int MISC_BASE_COSTS[76] = { + 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 300, 300, 300, 300, 300, + 300, 300, 300, 300, 300, 400, 400, 400, 400, 400, 400, 400, + 400, 400, 400, 500, 500, 500, 500, 500, 500, 500, 500, 500, + 500, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, + 600, 600, 600, 600 +}; +const int METAL_BASE_MULTIPLIERS[22] = { + 10, 25, 5, 75, 2, 5, 10, 20, 50, 2, 3, 5, 10, 20, 30, 40, + 50, 60, 70, 80, 90, 100 +}; +const int ITEM_SKILL_DIVISORS[4] = { 1, 2, 100, 10 }; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 4b08615520..4dae93e355 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -329,8 +329,10 @@ extern const char *const QUICK_REFERENCE; extern const uint BLACKSMITH_MAP_IDS[2][4]; -extern char *const ITEMS_DIALOG_TEXT1; -extern char *const ITEMS_DIALOG_TEXT2; +extern const char *const ITEMS_DIALOG_TEXT1; +extern const char *const ITEMS_DIALOG_TEXT2; +extern const char *const ITEMS_DIALOG_LINE1; +extern const char *const ITEMS_DIALOG_LINE2; extern const char *const BTN_BUY; extern const char *const BTN_SELL; @@ -354,6 +356,14 @@ extern const char *const ARMOR_NAMES[14]; extern const char *const ACCESSORY_NAMES[11]; extern const char *const MISC_NAMES[22]; +extern const int WEAPON_BASE_COSTS[35]; +extern const int ARMOR_BASE_COSTS[25]; +extern const int ACCESSORY_BASE_COSTS[11]; +extern const int MISC_MATERIAL_COSTS[22]; +extern const int MISC_BASE_COSTS[76]; +extern const int METAL_BASE_MULTIPLIERS[22]; +extern const int ITEM_SKILL_DIVISORS[4]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From 38df23ace070902d5808e77a7260f5d62ef88108 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 2 Feb 2015 22:11:08 -0500 Subject: XEEN: Implemented passRestrictions --- engines/xeen/dialogs_items.cpp | 78 ++++++++++++++++++++++++++++++++++-------- engines/xeen/dialogs_items.h | 6 +++- engines/xeen/items.h | 4 +++ engines/xeen/party.cpp | 13 +++---- engines/xeen/party.h | 2 +- engines/xeen/resources.cpp | 13 +++++++ engines/xeen/resources.h | 5 +++ 7 files changed, 99 insertions(+), 22 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index 67778777eb..511c27db5b 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -41,7 +41,8 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { Screen &screen = *_vm->_screen; Character *tempChar = c; - int typeNum = mode == ITEMMODE_4 || mode == ITEMMODE_COMBAT ? 3 : 0; + ItemCategory category = mode == ITEMMODE_4 || mode == ITEMMODE_COMBAT ? + CATEGORY_MISC : CATEGORY_WEAPON; int varA = mode == ITEMMODE_COMBAT ? 1 : 0; if (varA != 0) mode = ITEMMODE_CHAR_INFO; @@ -56,7 +57,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { bool redrawFlag = true; while (!_vm->shouldQuit()) { if (redrawFlag) { - if ((mode != ITEMMODE_CHAR_INFO || typeNum != 3) && mode != ITEMMODE_6 + if ((mode != ITEMMODE_CHAR_INFO || category != CATEGORY_MISC) && mode != ITEMMODE_6 && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) { _buttons[8]._bounds.moveTo(148, _buttons[8]._bounds.top); _buttons[9]._draw = false; @@ -80,7 +81,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { BTN_SELL, BTN_IDENTIFY, BTN_FIX); } else if (mode != ITEMMODE_6 && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) { msg = Common::String::format(ITEMS_DIALOG_TEXT1, - typeNum == 3 ? BTN_USE : BTN_EQUIP, + category == 3 ? BTN_USE : BTN_EQUIP, BTN_REMOVE, BTN_DISCARD, BTN_QUEST); } else if (mode == ITEMMODE_6) { msg = Common::String::format(ITEMS_DIALOG_TEXT2, BTN_ENCHANT); @@ -99,7 +100,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { Common::fill(&arr[0], &arr[40], 0); int var2 = -1; - if (mode == ITEMMODE_CHAR_INFO || typeNum != 3) { + if (mode == ITEMMODE_CHAR_INFO || category != 3) { _iconSprites.draw(screen, 8, Common::Point(148, 109)); } if (mode != ITEMMODE_6 && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) { @@ -128,21 +129,21 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { for (int idx = 0; idx < 9; ++idx) { _itemsDrawList[idx]._y = 10 + idx * 9; - switch (typeNum) { - case 0: + switch (category) { + case CATEGORY_WEAPON: if (c->_weapons[idx]._id) { if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8 || mode == ITEMMODE_6 || mode == ITEMMODE_4) { lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, arr[idx], idx + 1, - c->assembleItemName(idx, arr[idx], typeNum))); + c->assembleItemName(idx, arr[idx], category))); } else { lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2, arr[idx], idx + 1, - c->assembleItemName(idx, arr[idx], typeNum), + c->assembleItemName(idx, arr[idx], category), calcItemCost(c, idx, mode, mode == ITEMMODE_TO_GOLD ? 1 : c->_skills[MERCHANT], - typeNum) + category) )); } @@ -306,7 +307,7 @@ void ItemsDialog::setEquipmentIcons() { * Calculate the cost of an item */ int ItemsDialog::calcItemCost(Character *c, int itemIndex, int mode, - int skillLevel, int typeNum) { + int skillLevel, ItemCategory category) { int amount1 = 0, amount2 = 0, amount3 = 0, amount4 = 0; int result = 0; int level = skillLevel & 0x7f; @@ -329,10 +330,10 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, int mode, break; } - switch (typeNum) { - case 0: - case 1: - case 2: { + switch (category) { + case CATEGORY_WEAPON: + case CATEGORY_ARMOR: + case CATEGORY_ACCESSORY: { // 0=Weapons, 1=Armor, 2=Accessories XeenItem &i = (mode == 0) ? c->_weapons[itemIndex] : (mode == 1 ? c->_armor[itemIndex] : c->_accessories[itemIndex]); @@ -409,5 +410,54 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, int mode, return (mode == ITEMMODE_CHAR_INFO) ? 0 : result; } +bool ItemsDialog::passRestrictions(CharacterClass charClass, int itemId, + bool showError, ItemCategory category) const { + switch (charClass) { + case CLASS_KNIGHT: + case CLASS_PALADIN: + return true; + + case CLASS_ARCHER: + case CLASS_CLERIC: + case CLASS_SORCERER: + case CLASS_ROBBER: + case CLASS_NINJA: + case CLASS_BARBARIAN: + case CLASS_DRUID: + case CLASS_RANGER: { + if (!(ITEM_RESTRICTIONS[itemId + RESTRICTION_OFFSETS[category]] & + (1 << (charClass - CLASS_ARCHER)))) + return true; + break; + } + + default: + break; + } + + Common::String name; + switch (category) { + case CATEGORY_WEAPON: + name = WEAPON_NAMES[itemId]; + break; + case CATEGORY_ARMOR: + name = ARMOR_NAMES[itemId]; + break; + case CATEGORY_ACCESSORY: + name = ACCESSORY_NAMES[itemId]; + break; + case CATEGORY_MISC: + name = MISC_NAMES[itemId]; + break; + } + + if (showError) { + Common::String msg = Common::String::format(NOT_PROFICIENT, + CLASS_NAMES[charClass], name.c_str()); + ErrorScroll::show(_vm, msg, WT_FREEZE_WAIT); + } + + return false; +} } // End of namespace Xeen diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h index 1259b2524f..74be9215ce 100644 --- a/engines/xeen/dialogs_items.h +++ b/engines/xeen/dialogs_items.h @@ -55,7 +55,11 @@ private: void setEquipmentIcons(); - int calcItemCost(Character *c, int itemIndex, int mode, int skillLevel, int typeNum); + int calcItemCost(Character *c, int itemIndex, int mode, int skillLevel, + ItemCategory category); + + bool passRestrictions(CharacterClass charClass, int itemId, + bool showError, ItemCategory category) const; public: static Character *show(XeenEngine *vm, Character *c, ItemsMode mode); }; diff --git a/engines/xeen/items.h b/engines/xeen/items.h index 943b1876c2..bfc76084c7 100644 --- a/engines/xeen/items.h +++ b/engines/xeen/items.h @@ -34,6 +34,10 @@ enum BonusFlags { ITEMFLAG_BONUS_MASK = 0xBF, ITEMFLAG_CURSED = 0x40, ITEMFLAG_BROKEN = 0x80 }; +enum ItemCategory { + CATEGORY_WEAPON = 0, CATEGORY_ARMOR = 1, CATEGORY_ACCESSORY = 2, CATEGORY_MISC = 3 +}; + class XeenItem { public: int _material; diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 210852686a..2590abcf13 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -859,11 +859,12 @@ int Character::getNumAwards() const { * Assembles a full lines description for a specified item for use in * the Items dialog */ -Common::String Character::assembleItemName(int itemIndex, int displayNum, int typeNum) { +Common::String Character::assembleItemName(int itemIndex, int displayNum, + ItemCategory category) { Spells &spells = *Party::_vm->_spells; - switch (typeNum) { - case 0: { + switch (category) { + case CATEGORY_WEAPON: { // Weapons XeenItem &i = _weapons[itemIndex]; return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum, @@ -877,7 +878,7 @@ Common::String Character::assembleItemName(int itemIndex, int displayNum, int ty ); } - case 1: { + case CATEGORY_ARMOR: { // Armor XeenItem &i = _armor[itemIndex]; return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, @@ -890,7 +891,7 @@ Common::String Character::assembleItemName(int itemIndex, int displayNum, int ty ); } - case 2: { + case CATEGORY_ACCESSORY: { // Accessories XeenItem &i = _accessories[itemIndex]; return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, @@ -903,7 +904,7 @@ Common::String Character::assembleItemName(int itemIndex, int displayNum, int ty ); } - case 3: { + case CATEGORY_MISC: { // Misc XeenItem &i = _misc[itemIndex]; return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, diff --git a/engines/xeen/party.h b/engines/xeen/party.h index d719320766..6f70c4b49c 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -183,7 +183,7 @@ public: int getNumAwards() const; - Common::String assembleItemName(int itemIndex, int displayNum, int typeNum); + Common::String assembleItemName(int itemIndex, int displayNum, ItemCategory category); }; class Roster: public Common::Array<Character> { diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index b856baab47..3935104e1d 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1072,4 +1072,17 @@ const int METAL_BASE_MULTIPLIERS[22] = { }; const int ITEM_SKILL_DIVISORS[4] = { 1, 2, 100, 10 }; +const int RESTRICTION_OFFSETS[4] = { 0, 35, 49, 60 }; + +const int ITEM_RESTRICTIONS[86] = { + 0, 86, 86, 86, 86, 86, 86, 0, 6, 239, 239, 239, 2, 4, 4, 4, 4, + 6, 70, 70, 70, 70, 94, 70, 0, 4, 239, 86, 86, 86, 70, 70, 70, 70, + 0, 0, 0, 68, 100, 116, 125, 255, 255, 85, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const char *const NOT_PROFICIENT = + "\t000\v007\x3""c%ss are not proficient with a %s!"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 4dae93e355..bcd4daeabf 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -364,6 +364,11 @@ extern const int MISC_BASE_COSTS[76]; extern const int METAL_BASE_MULTIPLIERS[22]; extern const int ITEM_SKILL_DIVISORS[4]; +extern const int RESTRICTION_OFFSETS[4]; +extern const int ITEM_RESTRICTIONS[86]; + +extern const char *const NOT_PROFICIENT; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From f34c5ad9b65f626884736faf802d627dc2fe68c0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 2 Feb 2015 22:38:16 -0500 Subject: XEEN: Finished Items dailog loading block for weapons --- engines/xeen/dialogs_items.cpp | 34 +++++++++++++++++++++------------- engines/xeen/items.cpp | 4 ++-- engines/xeen/items.h | 2 +- engines/xeen/party.cpp | 6 +++--- engines/xeen/resources.cpp | 3 +++ engines/xeen/resources.h | 2 ++ 6 files changed, 32 insertions(+), 19 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index 511c27db5b..1043be8d9e 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -147,9 +147,14 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { )); } - // TODO + DrawStruct &ds = _itemsDrawList[idx]; + ds._sprites = &_equipSprites; + if (passRestrictions(c->_class, c->_weapons[idx]._id, true, CATEGORY_WEAPON)) + ds._frame = c->_weapons[idx]._frame; + else + ds._frame = 14; } else if (_itemsDrawList[idx]._sprites == nullptr) { - // TODO + lines.push_back(NO_ITEMS_AVAILABLE); } break; // TODO @@ -260,26 +265,26 @@ void ItemsDialog::setEquipmentIcons() { case 0: { XeenItem &i = _itemsCharacter._weapons[idx]; if (i._id <= 17) - i._equipped = 1; + i._frame = 1; else if (i._id <= 29 || i._id > 33) - i._equipped = 13; + i._frame = 13; else - i._equipped = 4; + i._frame = 4; break; } case 1: { XeenItem &i = _itemsCharacter._armor[idx]; if (i._id <= 7) - i._equipped = 3; + i._frame = 3; else if (i._id == 9) - i._equipped = 5; + i._frame = 5; else if (i._id == 10) - i._equipped = 9; + i._frame = 9; else if (i._id <= 12) - i._equipped = 10; + i._frame = 10; else - i._equipped = 6; + i._frame = 6; break; } @@ -288,11 +293,11 @@ void ItemsDialog::setEquipmentIcons() { if (i._id == 1) i._id = 8; else if (i._id == 2) - i._equipped = 12; + i._frame = 12; else if (i._id <= 7) - i._equipped = 7; + i._frame = 7; else - i._equipped = 11; + i._frame = 11; break; } @@ -410,6 +415,9 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, int mode, return (mode == ITEMMODE_CHAR_INFO) ? 0 : result; } +/** + * Return whether a given item passes class-based usage restrictions + */ bool ItemsDialog::passRestrictions(CharacterClass charClass, int itemId, bool showError, ItemCategory category) const { switch (charClass) { diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp index fd06af1024..5881fb378b 100644 --- a/engines/xeen/items.cpp +++ b/engines/xeen/items.cpp @@ -27,14 +27,14 @@ namespace Xeen { XeenItem::XeenItem() { _material = _id = _bonusFlags = 0; - _equipped = 0; + _frame = 0; } void XeenItem::synchronize(Common::Serializer &s) { s.syncAsByte(_material); s.syncAsByte(_id); s.syncAsByte(_bonusFlags); - s.syncAsByte(_equipped); + s.syncAsByte(_frame); } int XeenItem::getElementalCategory() const { diff --git a/engines/xeen/items.h b/engines/xeen/items.h index bfc76084c7..5a8c4d71a1 100644 --- a/engines/xeen/items.h +++ b/engines/xeen/items.h @@ -43,7 +43,7 @@ public: int _material; uint _id; int _bonusFlags; - int _equipped; + int _frame; public: XeenItem(); diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 2590abcf13..0a276b29cd 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -452,7 +452,7 @@ int Character::itemScan(int itemId) const { for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { const XeenItem &item = _weapons[idx]; - if (item._equipped && !(item._bonusFlags & 0xC0) && itemId < 11 + if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) { int mIndex = item.getAttributeCategory(); if (mIndex > 2) @@ -468,7 +468,7 @@ int Character::itemScan(int itemId) const { for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { const XeenItem &item = _armor[idx]; - if (item._equipped && !(item._bonusFlags & 0xC0)) { + if (item._frame && !(item._bonusFlags & 0xC0)) { if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) { int mIndex = item.getAttributeCategory(); if (mIndex > 2) @@ -500,7 +500,7 @@ int Character::itemScan(int itemId) const { for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { const XeenItem &item = _accessories[idx]; - if (item._equipped && !(item._bonusFlags & 0xC0) && itemId < 11 && itemId != 3) { + if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11 && itemId != 3) { if (item._material >= 59 && item._material <= 130) { int mIndex = item.getAttributeCategory(); if (mIndex > 2) diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 3935104e1d..8a23216e90 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1085,4 +1085,7 @@ const int ITEM_RESTRICTIONS[86] = { const char *const NOT_PROFICIENT = "\t000\v007\x3""c%ss are not proficient with a %s!"; +const char *const NO_ITEMS_AVAILABLE = "\x3""c\n" + "\t000No items available."; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index bcd4daeabf..c851db75a4 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -369,6 +369,8 @@ extern const int ITEM_RESTRICTIONS[86]; extern const char *const NOT_PROFICIENT; +extern const char *const NO_ITEMS_AVAILABLE; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From 4953b7954aca078be9655971f925f82c51e472db Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 4 Feb 2015 19:18:51 -0500 Subject: XEEN: Partial implementation of doItemOptions --- engines/xeen/combat.cpp | 2 + engines/xeen/combat.h | 2 + engines/xeen/dialogs_char_info.cpp | 4 +- engines/xeen/dialogs_error.cpp | 11 +- engines/xeen/dialogs_error.h | 2 +- engines/xeen/dialogs_items.cpp | 265 +++++++++++++++++++++++++++++++++++-- engines/xeen/dialogs_items.h | 11 +- engines/xeen/interface_map.h | 7 +- engines/xeen/items.cpp | 58 +++++++- engines/xeen/items.h | 28 +++- engines/xeen/party.cpp | 2 +- engines/xeen/party.h | 10 +- engines/xeen/resources.cpp | 37 ++++++ engines/xeen/resources.h | 27 ++++ engines/xeen/spells.cpp | 134 +++++++++++++++++++ engines/xeen/spells.h | 83 ++++++++++++ 16 files changed, 656 insertions(+), 27 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 6237e0c5ba..fec244b63a 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -34,6 +34,8 @@ Combat::Combat(XeenEngine *vm): _vm(vm) { Common::fill(&_elemScale[0], &_elemScale[12], 0); Common::fill(&_shooting[0], &_shooting[8], 0); _globalCombat = 0; + _whosTurn = -1; + _itemFlag = false; } void Combat::clear() { diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index c2554d5bf9..ef82de5af2 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -59,6 +59,8 @@ public: int _elemScale[12]; bool _shooting[8]; int _globalCombat; + int _whosTurn; + bool _itemFlag; public: Combat(XeenEngine *vm); diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp index 1d907cf7d9..0c71bfb0be 100644 --- a/engines/xeen/dialogs_char_info.cpp +++ b/engines/xeen/dialogs_char_info.cpp @@ -185,7 +185,7 @@ void CharacterInfo::execute(int charIndex) { case Common::KEYCODE_i: _vm->_mode = oldMode; - _vm->_treasure._v1 = _vm->_mode == MODE_InCombat; + _vm->_combat->_itemFlag = _vm->_mode == MODE_InCombat; c = ItemsDialog::show(_vm, c, ITEMMODE_CHAR_INFO); if (!c) { @@ -209,7 +209,7 @@ exit: w.close(); intf.unhighlightChar(); _vm->_mode = oldMode; - _vm->_treasure._v1 = false; + _vm->_combat->_itemFlag = false; } /** diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp index e8512216c7..a58e0e9e78 100644 --- a/engines/xeen/dialogs_error.cpp +++ b/engines/xeen/dialogs_error.cpp @@ -38,7 +38,16 @@ void ErrorScroll::execute(const Common::String &msg, ErrorWaitType waitType) { EventsManager &events = *_vm->_events; Window &w = screen._windows[6]; - Common::String s = Common::String::format("\x03c\v010\t000%s", msg.c_str()); + Common::String s; + if (waitType == WT_UNFORMATTED) { + // This type isn't technically a waiting type, but it saved on adding + // yet another parameter + waitType = WT_FREEZE_WAIT; + s = msg; + } else { + s = Common::String::format("\x03c\v010\t000%s", msg.c_str()); + } + w.open(); w.writeString(s); w.update(); diff --git a/engines/xeen/dialogs_error.h b/engines/xeen/dialogs_error.h index ba36f285cf..1a86afce87 100644 --- a/engines/xeen/dialogs_error.h +++ b/engines/xeen/dialogs_error.h @@ -28,7 +28,7 @@ namespace Xeen { enum ErrorWaitType { WT_FREEZE_WAIT = 0, WT_NONFREEZED_WAIT = 1, - WT_2 = 2, WT_3 = 3}; + WT_2 = 2, WT_3 = 3, WT_UNFORMATTED = 9 }; class ErrorScroll: public ButtonContainer { private: diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index 1043be8d9e..634fb2de39 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -40,7 +40,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { Party &party = *_vm->_party; Screen &screen = *_vm->_screen; - Character *tempChar = c; + Character *startingChar = c; ItemCategory category = mode == ITEMMODE_4 || mode == ITEMMODE_COMBAT ? CATEGORY_MISC : CATEGORY_WEAPON; int varA = mode == ITEMMODE_COMBAT ? 1 : 0; @@ -130,8 +130,13 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { _itemsDrawList[idx]._y = 10 + idx * 9; switch (category) { - case CATEGORY_WEAPON: - if (c->_weapons[idx]._id) { + case CATEGORY_WEAPON: + case CATEGORY_ARMOR: + case CATEGORY_ACCESSORY: { + XeenItem &i = (category == CATEGORY_WEAPON) ? c->_weapons[idx] : + ((category == CATEGORY_ARMOR) ? c->_armor[idx] : c->_accessories[idx]); + + if (i._id) { if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8 || mode == ITEMMODE_6 || mode == ITEMMODE_4) { lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, @@ -142,26 +147,143 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { arr[idx], idx + 1, c->assembleItemName(idx, arr[idx], category), calcItemCost(c, idx, mode, - mode == ITEMMODE_TO_GOLD ? 1 : c->_skills[MERCHANT], + mode == ITEMMODE_TO_GOLD ? 1 : startingChar->_skills[MERCHANT], category) )); } DrawStruct &ds = _itemsDrawList[idx]; ds._sprites = &_equipSprites; - if (passRestrictions(c->_class, c->_weapons[idx]._id, true, CATEGORY_WEAPON)) - ds._frame = c->_weapons[idx]._frame; + if (passRestrictions(c->_class, i._id, true, CATEGORY_WEAPON)) + ds._frame = i._frame; else ds._frame = 14; } else if (_itemsDrawList[idx]._sprites == nullptr) { lines.push_back(NO_ITEMS_AVAILABLE); } break; - // TODO + } + + case CATEGORY_MISC: { + XeenItem &i = c->_misc[idx]; + _itemsDrawList[idx]._sprites = nullptr; + + if (i._material == 0) { + // No item + if (idx == 0) { + lines.push_back(NO_ITEMS_AVAILABLE); + } + } else { + ItemsMode tempMode = mode; + int skill = startingChar->_skills[MERCHANT]; + + if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8 + || mode == ITEMMODE_6 || mode == ITEMMODE_4) { + tempMode = ITEMMODE_6; + } else if (mode == ITEMMODE_TO_GOLD) { + skill = 1; + } + + lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2, + arr[idx], idx + 1, + c->assembleItemName(idx, arr[idx], category), + calcItemCost(c, idx, tempMode, skill, category) + )); + } + break; + } + + default: + break; + } + } + while (lines.size() < INV_ITEMS_TOTAL) + lines.push_back(""); + + // Draw out overall text and the list of items + switch (mode) { + case ITEMMODE_CHAR_INFO: + case ITEMMODE_8: + screen._windows[30].writeString(Common::String::format(X_FOR_THE_Y, + category == CATEGORY_MISC ? "\x3l" : "\x3c", + CATEGORY_NAMES[category], c->_name.c_str(), CLASS_NAMES[c->_class], + category == CATEGORY_MISC ? FMT_CHARGES : " ", + lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(), + lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(), + lines[8].c_str() + )); + + case ITEMMODE_BLACKSMITH: { + // Original uses var in this block that's never set?! + const int v1 = 0; + screen._windows[30].writeString(Common::String::format(AVAILABLE_GOLD_COST, + CATEGORY_NAMES[category], + v1 ? "" : "s", party._gold, + lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(), + lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(), + lines[8].c_str() + )); + break; + } + + case ITEMMODE_2: + case ITEMMODE_4: + case ITEMMODE_6: + case ITEMMODE_9: + case ITEMMODE_10: + case ITEMMODE_TO_GOLD: + screen._windows[30].writeString(Common::String::format(X_FOR_Y, + CATEGORY_NAMES[category], startingChar->_name.c_str(), + (mode == ITEMMODE_4 || mode == ITEMMODE_6) ? CHARGES : COST, + lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(), + lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(), + lines[8].c_str() + )); + break; + + case ITEMMODE_3: + case ITEMMODE_5: + screen._windows[30].writeString(Common::String::format(X_FOR_Y_GOLD, + CATEGORY_NAMES[category], c->_name.c_str(), party._gold, CHARGES, + lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(), + lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(), + lines[8].c_str() + )); + break; + + default: + break; + } + + // Draw the glyphs for the items + screen._windows[0].drawList(_itemsDrawList, INV_ITEMS_TOTAL); + screen._windows[0].update(); + + if (var2 != -1) { + int actionIndex = -1; + switch (mode) { + case ITEMMODE_BLACKSMITH: + actionIndex = 0; + break; + case ITEMMODE_2: + actionIndex = 1; + break; + case ITEMMODE_9: + actionIndex = 3; + break; + case ITEMMODE_10: + actionIndex = 2; + break; default: break; } + + if (actionIndex >= 0) { + doItemOptions(*c, actionIndex, var2, category, mode); + } } + + // TODO } return c; @@ -311,7 +433,7 @@ void ItemsDialog::setEquipmentIcons() { /** * Calculate the cost of an item */ -int ItemsDialog::calcItemCost(Character *c, int itemIndex, int mode, +int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode, int skillLevel, ItemCategory category) { int amount1 = 0, amount2 = 0, amount3 = 0, amount4 = 0; int result = 0; @@ -468,4 +590,131 @@ bool ItemsDialog::passRestrictions(CharacterClass charClass, int itemId, return false; } +bool ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, ItemCategory category, + ItemsMode mode) { + Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + Spells &spells = *_vm->_spells; + + XeenItem *itemCategories[4] = { &c._weapons[0], &c._armor[0], &c._accessories[0], &c._misc[0] }; + XeenItem *items = itemCategories[category]; + if (!items[0]._id) + return false; + + Window &w = screen._windows[11]; + SpriteResource escSprites; + if (itemIndex < 0 || itemIndex > 8) { + saveButtons(); + + escSprites.load("esc.icn"); + addButton(Common::Rect(235, 111, 259, 131), Common::KEYCODE_ESCAPE, &escSprites); + addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1, &escSprites, false); + addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2, &escSprites, false); + addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3, &escSprites, false); + addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4, &escSprites, false); + addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5, &escSprites, false); + addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6, &escSprites, false); + addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, &escSprites, false); + addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, &escSprites, false); + addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, &escSprites, false); + + w.open(); + w.writeString(Common::String::format(WHICH_ITEM, ITEM_ACTIONS[actionIndex])); + _iconSprites.draw(screen, 0, Common::Point(235, 111)); + w.update(); + + while (!_vm->shouldQuit()) { + while (!_buttonValue) { + events.pollEventsAndWait(); + checkEvents(_vm); + if (_vm->shouldQuit()) + return false; + } + + if (_buttonValue == Common::KEYCODE_ESCAPE) { + itemIndex = -1; + break; + } else if (_buttonValue >= Common::KEYCODE_1 && _buttonValue <= Common::KEYCODE_9) { + // Check whether there's an item at the selected index + int selectedIndex = _buttonValue - Common::KEYCODE_1; + if (!items[selectedIndex]._id) + continue; + + itemIndex = selectedIndex; + break; + } + } + + w.close(); + restoreButtons(); + } + + if (itemIndex != -1) { + switch (mode) { + case ITEMMODE_CHAR_INFO: + case ITEMMODE_8: + switch (actionIndex) { + case 0: + c._items[category].equipItem(itemIndex); + break; + case 1: + c._items[category].removeItem(itemIndex); + break; + case 2: + if (!party._mazeId) { + ErrorScroll::show(_vm, WHATS_YOUR_HURRY); + } else { + XeenItem &i = c._misc[itemIndex]; + + Condition condition = c.worstCondition(); + switch (condition) { + case SLEEP: + case PARALYZED: + case UNCONSCIOUS: + case DEAD: + case STONED: + case ERADICATED: + ErrorScroll::show(_vm, Common::String::format(IN_NO_CONDITION, c._name.c_str())); + break; + default: + if (combat._itemFlag) { + ErrorScroll::show(_vm, USE_ITEM_IN_COMBAT); + } else if (i._id && (i._bonusFlags & ITEMFLAG_BONUS_MASK) + && !(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED))) { + int bonus = (i._bonusFlags & ITEMFLAG_BONUS_MASK) - 1; + i._bonusFlags = bonus; + _oldCharacter = &c; + + screen._windows[30].close(); + screen._windows[29].close(); + screen._windows[24].close(); + spells.doSpell(i._id); + + if (!bonus) { + c._items[category].discardItem(itemIndex); + } + } else { + ErrorScroll::show(_vm, Common::String::format(NO_SPECIAL_ABILITIES, + c.assembleItemName(itemIndex, 15, category).c_str() + )); + } + } + } + case 3: + // TODO: Remaining switches + default: + break; + } + } + } + + intf._charsShooting = false; + intf.moveMonsters(); + combat._whosTurn = -1; + return true; +} + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h index 74be9215ce..c30eaa9a4a 100644 --- a/engines/xeen/dialogs_items.h +++ b/engines/xeen/dialogs_items.h @@ -30,8 +30,8 @@ namespace Xeen { enum ItemsMode { - ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_2 = 2, - ITEMMODE_4 = 4, ITEMMODE_6 = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, + ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_2 = 2, ITEMMODE_3 = 3, + ITEMMODE_4 = 4, ITEMMODE_5 = 5, ITEMMODE_6 = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, ITEMMODE_9 = 9, ITEMMODE_10 = 10, ITEMMODE_TO_GOLD = 11 }; @@ -42,7 +42,7 @@ private: SpriteResource _equipSprites; Character _itemsCharacter; Character *_oldCharacter; - DrawStruct _itemsDrawList[9]; + DrawStruct _itemsDrawList[INV_ITEMS_TOTAL]; ItemsDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm), _oldCharacter(nullptr) {} @@ -55,11 +55,14 @@ private: void setEquipmentIcons(); - int calcItemCost(Character *c, int itemIndex, int mode, int skillLevel, + int calcItemCost(Character *c, int itemIndex, ItemsMode mode, int skillLevel, ItemCategory category); bool passRestrictions(CharacterClass charClass, int itemId, bool showError, ItemCategory category) const; + + bool doItemOptions(Character &c, int actionIndex, int itemIndex, + ItemCategory category, ItemsMode mode); public: static Character *show(XeenEngine *vm, Character *c, ItemsMode mode); }; diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index fb448e1f29..197f239404 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -111,7 +111,6 @@ protected: bool _flipSky; bool _flipDefaultGround; bool _isShooting; - bool _charsShooting; bool _thinWall; bool _isAnimReset; int _blessedUIFrame; @@ -125,8 +124,6 @@ protected: void animate3d(); - void moveMonsters(); - void drawMiniMap(); virtual void setup(); @@ -144,6 +141,7 @@ public: int _objNumber; int _overallFrame; int _batUIFrame; + bool _charsShooting; public: InterfaceMap(XeenEngine *vm); @@ -166,6 +164,9 @@ public: void drawOutdoors(); void assembleBorder(); + + void moveMonsters(); + }; } // End of namespace Xeen diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp index 5881fb378b..13418262bd 100644 --- a/engines/xeen/items.cpp +++ b/engines/xeen/items.cpp @@ -26,6 +26,10 @@ namespace Xeen { XeenItem::XeenItem() { + clear(); +} + +void XeenItem::clear() { _material = _id = _bonusFlags = 0; _frame = 0; } @@ -54,9 +58,61 @@ int XeenItem::getAttributeCategory() const { return idx; } +/*------------------------------------------------------------------------*/ + +InventoryItems::InventoryItems() : Common::Array<XeenItem>((XeenItem *)nullptr, INV_ITEMS_TOTAL) { +} + +void InventoryItems::discardItem(int itemIndex) { + operator[](itemIndex).clear(); + sort(); +} + +void InventoryItems::sort() { + for (uint idx = 0; idx < size(); ++idx) { + if (operator[](idx)._id == 0) { + // Found empty slot + operator[](idx).clear(); + + // Scan through the rest of the list to find any item + for (uint idx2 = idx + 1; idx2 < size(); ++idx2) { + if (operator[](idx2)._id) { + // Found an item, so move it into the blank slot + operator[](idx) = operator[](idx2); + operator[](idx2).clear(); + break; + } + } + } + } +} + +void InventoryItems::equipItem(int itemIndex) { + error("TODO"); +} + +void InventoryItems::removeItem(int itemIndex) { + error("TODO"); +} + +/*------------------------------------------------------------------------*/ + +InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor, + InventoryItems &accessories, InventoryItems &misc) { + _itemSets[0] = &weapons; + _itemSets[1] = &armor; + _itemSets[2] = &accessories; + _itemSets[3] = &misc; +} + +InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) { + return *_itemSets[category]; +} + +/*------------------------------------------------------------------------*/ + Treasure::Treasure() { _hasItems = false; - _v1 = false; } } // End of namespace Xeen diff --git a/engines/xeen/items.h b/engines/xeen/items.h index 5a8c4d71a1..c0b82b9fce 100644 --- a/engines/xeen/items.h +++ b/engines/xeen/items.h @@ -24,11 +24,13 @@ #define XEEN_ITEMS_H #include "common/scummsys.h" +#include "common/array.h" #include "common/serializer.h" namespace Xeen { #define TOTAL_ITEMS 10 +#define INV_ITEMS_TOTAL 9 enum BonusFlags { ITEMFLAG_BONUS_MASK = 0xBF, ITEMFLAG_CURSED = 0x40, ITEMFLAG_BROKEN = 0x80 @@ -47,6 +49,8 @@ public: public: XeenItem(); + void clear(); + void synchronize(Common::Serializer &s); int getElementalCategory() const; @@ -54,6 +58,29 @@ public: int getAttributeCategory() const; }; +class InventoryItems : public Common::Array<XeenItem> { +public: + InventoryItems(); + + void discardItem(int itemIndex); + + void equipItem(int itemIndex); + + void removeItem(int itemIndex); + + void sort(); +}; + +class InventoryItemsGroup { +private: + InventoryItems *_itemSets[4]; +public: + InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor, + InventoryItems &accessories, InventoryItems &misc); + + InventoryItems &operator[](ItemCategory category); +}; + class Treasure { public: XeenItem _misc[TOTAL_ITEMS]; @@ -61,7 +88,6 @@ public: XeenItem _armor[TOTAL_ITEMS]; XeenItem _weapons[TOTAL_ITEMS]; bool _hasItems; - bool _v1; public: Treasure(); }; diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 0a276b29cd..7d47eafaf4 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -43,7 +43,7 @@ void AttributePair::synchronize(Common::Serializer &s) { /*------------------------------------------------------------------------*/ -Character::Character() { +Character::Character(): _items(_weapons, _armor, _accessories, _misc) { _sex = MALE; _race = HUMAN; _xeenSide = 0; diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 6f70c4b49c..73de7065aa 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -74,7 +74,6 @@ enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, #define XEEN_TOTAL_CHARACTERS 24 #define MAX_ACTIVE_PARTY 6 #define TOTAL_STATS 7 -#define INV_ITEMS_TOTAL 9 class XeenEngine; @@ -115,10 +114,11 @@ public: bool _hasSpells; int _currentSpell; int _quickOption; - XeenItem _weapons[INV_ITEMS_TOTAL]; - XeenItem _armor[INV_ITEMS_TOTAL]; - XeenItem _accessories[INV_ITEMS_TOTAL]; - XeenItem _misc[INV_ITEMS_TOTAL]; + InventoryItemsGroup _items; + InventoryItems _weapons; + InventoryItems _armor; + InventoryItems _accessories; + InventoryItems _misc; int _lloydSide; AttributePair _fireResistence; AttributePair _coldResistence; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 8a23216e90..1f1c979f7a 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1088,4 +1088,41 @@ const char *const NOT_PROFICIENT = const char *const NO_ITEMS_AVAILABLE = "\x3""c\n" "\t000No items available."; +const char *const CATEGORY_NAMES[4] = { "Weapons", "Armor", "Accessories", "Miscellaneous" }; + +const char *const X_FOR_THE_Y = + "\x1\fd\r%s\v000\t000%s for %s the %s%s\v011\x2%s%s%s%s%s%s%s%s%s\x1\fd"; + +const char *const X_FOR_Y = + "\x1\xC""d\r\x3l\v000\t000%s for %s\x3r\t000%s\x3l\v011\x2%s%s%s%s%s%s%s%s%s\x1\xC""d"; + +const char *const X_FOR_Y_GOLD = + "\x1\fd\r\x3l\v000\t000%s for %s\t150Gold - %lu%s\x3l\v011" + "\x2%s%s%s%s%s%s%s%s%s\x1\fd"; + +const char *const FMT_CHARGES = "\x3rr\t000Charges\x3l"; + +const char *const AVAILABLE_GOLD_COST = + "\x1\fd\r\x3l\v000\t000Available %s%s\t150Gold - %lu\x3r\t000Cost" + "\x3l\v011\x2%s%s%s%s%s%s%s%s%s\x1\xC""d"; + +const char *const CHARGES = "Charges"; + +const char *const COST = "Cost"; + +const char *const ITEM_ACTIONS[7] = { + "Equip", "Remove", "Use", "Discard", "Enchant", "Recharge", "Gold" +}; +const char *const WHICH_ITEM = "\t010\v005%s which item?"; + +const char *const WHATS_YOUR_HURRY = "\v007What's your hurry?\n" + "Wait till you get out of here!"; + +const char *const USE_ITEM_IN_COMBAT = + "\v007To use an item in Combat, invoke the Use command on your turn!"; + +const char *const NO_SPECIAL_ABILITIES = "\v005\x3""c%s\fdhas no special abilities!"; + +const char *const CANT_CAST_WHILE_ENGAGED = "\x03c\v007Can't cast %s while engaged!"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index c851db75a4..88e01cdb51 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -371,6 +371,33 @@ extern const char *const NOT_PROFICIENT; extern const char *const NO_ITEMS_AVAILABLE; +extern const char *const CATEGORY_NAMES[4]; + +extern const char *const X_FOR_THE_Y; + +extern const char *const X_FOR_Y; + +extern const char *const X_FOR_Y_GOLD; + +extern const char *const FMT_CHARGES; + +extern const char *const AVAILABLE_GOLD_COST; + +extern const char *const CHARGES; + +extern const char *const COST; + +extern const char *const ITEM_ACTIONS[7]; +extern const char *const WHICH_ITEM; + +extern const char *const WHATS_YOUR_HURRY; + +extern const char *const USE_ITEM_IN_COMBAT; + +extern const char *const NO_SPECIAL_ABILITIES; + +extern const char *const CANT_CAST_WHILE_ENGAGED; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 588fa1b510..3492510db9 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -56,4 +56,138 @@ int Spells::calcSpellPoints(int spellId, int expenseFactor) const { return (amount >= 0) ? amount : amount * -1 * expenseFactor; } +typedef void(Spells::*SpellMethodPtr)(); + +void Spells::doSpell(int spellId) { + static const SpellMethodPtr SPELL_LIST[73] = { + &Spells::light, &Spells::awaken, &Spells::magicArrow, &Spells::firstAid, + &Spells::flyingFist, &Spells::energyBlast, &Spells::sleep, + &Spells::revitalize, &Spells::cureWounds, &Spells::sparks, + + &Spells::shrapMetal, &Spells::insectSpray, &Spells::toxicCloud, + &Spells::protectionFromElements, &Spells::pain, &Spells::jump, + &Spells::beastMaster, &Spells::clairvoyance, &Spells::turnUndead, + &Spells::levitate, + + &Spells::wizardEye, &Spells::bless, &Spells::identifyMonster, + &Spells::lightningBolt, &Spells::holyBonus, &Spells::powerCure, + &Spells::naturesCure, &Spells::lloydsBeacon, &Spells::powerShield, + &Spells::heroism, + + &Spells::hypnotize, &Spells::walkOnWater, &Spells::frostByte, + &Spells::detectMonster, &Spells::fireball, &Spells::coldRay, + &Spells::curePoison, &Spells::acidSpray, &Spells::timeDistortion, + &Spells::dragonSleep, + + &Spells::cureDisease, &Spells::teleport, &Spells::fingerOfDeath, + &Spells::cureParalysis, &Spells::golemStopper, &Spells::poisonVolley, + &Spells::deadlySwarm, &Spells::superShelter, &Spells::dayOfProtection, + &Spells::dayOfSorcery, + + &Spells::createFood, &Spells::fieryFlail, &Spells::rechargeItem, + &Spells::fantasticFreeze, &Spells::townPortal, &Spells::stoneToFlesh, + &Spells::raiseDead, &Spells::etherialize, &Spells::dancingSword, + &Spells::moonRay, + + &Spells::massDistortion, &Spells::prismaticLight, &Spells::enchantItem, + &Spells::incinerate, &Spells::holyWord, &Spells::resurrection, + &Spells::elementalStorm, &Spells::megaVolts, &Spells::inferno, + &Spells::sunRay, + + &Spells::implosion, &Spells::starBurst, &Spells::divineIntervention + }; + + if (_vm->_mode == MODE_InCombat) { + if (spellId == 15 || spellId == 20 || spellId == 27 || spellId == 41 + || spellId == 47 || spellId == 54 || spellId == 57) { + ErrorScroll::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED, + _spellNames[spellId].c_str()), WT_UNFORMATTED); + return; + } + } + + (this->*SPELL_LIST[spellId])(); +} + +void Spells::light() { error("TODO: spell"); } +void Spells::awaken() { error("TODO: spell"); } +void Spells::magicArrow() { error("TODO: spell"); } +void Spells::firstAid() { error("TODO: spell"); } +void Spells::flyingFist() { error("TODO: spell"); } +void Spells::energyBlast() { error("TODO: spell"); } +void Spells::sleep() { error("TODO: spell"); } +void Spells::revitalize() { error("TODO: spell"); } +void Spells::cureWounds() { error("TODO: spell"); } +void Spells::sparks() { error("TODO: spell"); } + +void Spells::shrapMetal() { error("TODO: spell"); } +void Spells::insectSpray() { error("TODO: spell"); } +void Spells::toxicCloud() { error("TODO: spell"); } +void Spells::protectionFromElements() { error("TODO: spell"); } +void Spells::pain() { error("TODO: spell"); } +void Spells::jump() { error("TODO: spell"); } // Not while engaged +void Spells::beastMaster() { error("TODO: spell"); } +void Spells::clairvoyance() { error("TODO: spell"); } +void Spells::turnUndead() { error("TODO: spell"); } +void Spells::levitate() { error("TODO: spell"); } + +void Spells::wizardEye() { error("TODO: spell"); } // Not while engaged +void Spells::bless() { error("TODO: spell"); } +void Spells::identifyMonster() { error("TODO: spell"); } +void Spells::lightningBolt() { error("TODO: spell"); } +void Spells::holyBonus() { error("TODO: spell"); } +void Spells::powerCure() { error("TODO: spell"); } +void Spells::naturesCure() { error("TODO: spell"); } +void Spells::lloydsBeacon() { error("TODO: spell"); } // Not while engaged +void Spells::powerShield() { error("TODO: spell"); } +void Spells::heroism() { error("TODO: spell"); } + +void Spells::hypnotize() { error("TODO: spell"); } +void Spells::walkOnWater() { error("TODO: spell"); } +void Spells::frostByte() { error("TODO: spell"); } +void Spells::detectMonster() { error("TODO: spell"); } +void Spells::fireball() { error("TODO: spell"); } +void Spells::coldRay() { error("TODO: spell"); } +void Spells::curePoison() { error("TODO: spell"); } +void Spells::acidSpray() { error("TODO: spell"); } +void Spells::timeDistortion() { error("TODO: spell"); } +void Spells::dragonSleep() { error("TODO: spell"); } + +void Spells::cureDisease() { error("TODO: spell"); } +void Spells::teleport() { error("TODO: spell"); } // Not while engaged +void Spells:: fingerOfDeath() { error("TODO: spell"); } +void Spells::cureParalysis() { error("TODO: spell"); } +void Spells::golemStopper() { error("TODO: spell"); } +void Spells::poisonVolley() { error("TODO: spell"); } +void Spells::deadlySwarm() { error("TODO: spell"); } +void Spells::superShelter() { error("TODO: spell"); } // Not while engaged +void Spells::dayOfProtection() { error("TODO: spell"); } +void Spells::dayOfSorcery() { error("TODO: spell"); } + +void Spells::createFood() { error("TODO: spell"); } +void Spells::fieryFlail() { error("TODO: spell"); } +void Spells::rechargeItem() { error("TODO: spell"); } +void Spells::fantasticFreeze() { error("TODO: spell"); } +void Spells::townPortal() { error("TODO: spell"); } // Not while engaged +void Spells::stoneToFlesh() { error("TODO: spell"); } +void Spells::raiseDead() { error("TODO: spell"); } +void Spells::etherialize() { error("TODO: spell"); } // Not while engaged +void Spells::dancingSword() { error("TODO: spell"); } +void Spells::moonRay() { error("TODO: spell"); } + +void Spells::massDistortion() { error("TODO: spell"); } +void Spells::prismaticLight() { error("TODO: spell"); } +void Spells::enchantItem() { error("TODO: spell"); } +void Spells::incinerate() { error("TODO: spell"); } +void Spells::holyWord() { error("TODO: spell"); } +void Spells::resurrection() { error("TODO: spell"); } +void Spells::elementalStorm() { error("TODO: spell"); } +void Spells::megaVolts() { error("TODO: spell"); } +void Spells::inferno() { error("TODO: spell"); } +void Spells::sunRay() { error("TODO: spell"); } + +void Spells::implosion() { error("TODO: spell"); } +void Spells::starBurst() { error("TODO: spell"); } +void Spells::divineIntervention() { error("TODO: spell"); } + } // End of namespace Xeen diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h index 96f491684e..241d35dca7 100644 --- a/engines/xeen/spells.h +++ b/engines/xeen/spells.h @@ -37,6 +37,88 @@ private: XeenEngine *_vm; void load(); + + // Spell list + void light(); + void awaken(); + void magicArrow(); + void firstAid(); + void flyingFist(); + void energyBlast(); + void sleep(); + void revitalize(); + void cureWounds(); + void sparks(); + + void shrapMetal(); + void insectSpray(); + void toxicCloud(); + void protectionFromElements(); + void pain(); + void jump(); // Not while engaged + void beastMaster(); + void clairvoyance(); + void turnUndead(); + void levitate(); + + void wizardEye(); // Not while engaged + void bless(); + void identifyMonster(); + void lightningBolt(); + void holyBonus(); + void powerCure(); + void naturesCure(); + void lloydsBeacon(); // Not while engaged + void powerShield(); + void heroism(); + + void hypnotize(); + void walkOnWater(); + void frostByte(); + void detectMonster(); + void fireball(); + void coldRay(); + void curePoison(); + void acidSpray(); + void timeDistortion(); + void dragonSleep(); + + void cureDisease(); + void teleport(); // Not while engaged + void fingerOfDeath(); + void cureParalysis(); + void golemStopper(); + void poisonVolley(); + void deadlySwarm(); + void superShelter(); // Not while engaged + void dayOfProtection(); + void dayOfSorcery(); + + void createFood(); + void fieryFlail(); + void rechargeItem(); + void fantasticFreeze(); + void townPortal(); // Not while engaged + void stoneToFlesh(); + void raiseDead(); + void etherialize(); // Not while engaged + void dancingSword(); + void moonRay(); + + void massDistortion(); + void prismaticLight(); + void enchantItem(); + void incinerate(); + void holyWord(); + void resurrection(); + void elementalStorm(); + void megaVolts(); + void inferno(); + void sunRay(); + + void implosion(); + void starBurst(); + void divineIntervention(); public: Common::StringArray _spellNames; Common::StringArray _maeNames; @@ -48,6 +130,7 @@ public: int calcSpellPoints(int spellId, int expenseFactor) const; + void doSpell(int spellId); }; } // End of namespace Xeen -- cgit v1.2.3 From 8eb9ad50f8ddf23147b999fa40c6231a1a623d41 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 4 Feb 2015 20:22:59 -0500 Subject: XEEN: Split Character class into it's own file --- engines/xeen/character.cpp | 1008 ++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/character.h | 231 ++++++++++ engines/xeen/items.cpp | 86 ---- engines/xeen/items.h | 54 +-- engines/xeen/module.mk | 1 + engines/xeen/party.cpp | 891 --------------------------------------- engines/xeen/party.h | 141 ------- 7 files changed, 1241 insertions(+), 1171 deletions(-) create mode 100644 engines/xeen/character.cpp create mode 100644 engines/xeen/character.h (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp new file mode 100644 index 0000000000..f712e78e8c --- /dev/null +++ b/engines/xeen/character.cpp @@ -0,0 +1,1008 @@ +/* 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 "xeen/character.h" +#include "xeen/resources.h" +#include "xeen/xeen.h" + +namespace Xeen { + +XeenItem::XeenItem() { + clear(); +} + +void XeenItem::clear() { + _material = _id = _bonusFlags = 0; + _frame = 0; +} + +void XeenItem::synchronize(Common::Serializer &s) { + s.syncAsByte(_material); + s.syncAsByte(_id); + s.syncAsByte(_bonusFlags); + s.syncAsByte(_frame); +} + +int XeenItem::getElementalCategory() const { + int idx; + for (idx = 0; ELEMENTAL_CATEGORIES[idx] < _material; ++idx) + ; + + return idx; +} + +int XeenItem::getAttributeCategory() const { + int m = _material - 59; + int idx; + for (idx = 0; ATTRIBUTE_CATEGORIES[idx] < m; ++idx) + ; + + return idx; +} + +/*------------------------------------------------------------------------*/ + +InventoryItems::InventoryItems() { + resize(INV_ITEMS_TOTAL); +} + +void InventoryItems::discardItem(int itemIndex) { + operator[](itemIndex).clear(); + sort(); +} + +void InventoryItems::sort() { + for (uint idx = 0; idx < size(); ++idx) { + if (operator[](idx)._id == 0) { + // Found empty slot + operator[](idx).clear(); + + // Scan through the rest of the list to find any item + for (uint idx2 = idx + 1; idx2 < size(); ++idx2) { + if (operator[](idx2)._id) { + // Found an item, so move it into the blank slot + operator[](idx) = operator[](idx2); + operator[](idx2).clear(); + break; + } + } + } + } +} + +void InventoryItems::equipItem(int itemIndex) { + error("TODO"); +} + +void InventoryItems::removeItem(int itemIndex) { + error("TODO"); +} + +/*------------------------------------------------------------------------*/ + +InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor, + InventoryItems &accessories, InventoryItems &misc) { + _itemSets[0] = &weapons; + _itemSets[1] = &armor; + _itemSets[2] = &accessories; + _itemSets[3] = &misc; +} + +InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) { + return *_itemSets[category]; +} + +/*------------------------------------------------------------------------*/ + + +void AttributePair::synchronize(Common::Serializer &s) { + s.syncAsByte(_permanent); + s.syncAsByte(_temporary); +} + +/*------------------------------------------------------------------------*/ + +AttributePair::AttributePair() { + _temporary = _permanent = 0; +} + +/*------------------------------------------------------------------------*/ + +Character::Character(): _items(_weapons, _armor, _accessories, _misc) { + _sex = MALE; + _race = HUMAN; + _xeenSide = 0; + _class = CLASS_KNIGHT; + _ACTemp = 0; + _birthDay = 0; + _tempAge = 0; + Common::fill(&_skills[0], &_skills[18], 0); + Common::fill(&_awards[0], &_awards[128], false); + Common::fill(&_spells[0], &_spells[39], 0); + _lloydMap = 0; + _hasSpells = false; + _currentSpell = 0; + _quickOption = 0; + _lloydSide = 0; + Common::fill(&_conditions[0], &_conditions[16], 0); + _townUnknown = 0; + _savedMazeId = 0; + _currentHp = 0; + _currentSp = 0; + _birthYear = 0; + _experience = 0; + _currentAdventuringSpell = 0; + _currentCombatSpell = 0; +} + +void Character::synchronize(Common::Serializer &s) { + char name[16]; + Common::fill(&name[0], &name[16], '\0'); + strncpy(name, _name.c_str(), 16); + s.syncBytes((byte *)name, 16); + + if (s.isLoading()) + _name = Common::String(name); + + s.syncAsByte(_sex); + s.syncAsByte(_race); + s.syncAsByte(_xeenSide); + s.syncAsByte(_class); + + _might.synchronize(s); + _intellect.synchronize(s); + _personality.synchronize(s); + _endurance.synchronize(s); + _speed.synchronize(s); + _accuracy.synchronize(s); + _luck.synchronize(s); + s.syncAsByte(_ACTemp); + _level.synchronize(s); + s.syncAsByte(_birthDay); + s.syncAsByte(_tempAge); + + // Synchronize the skill list + for (int idx = 0; idx < 18; ++idx) + s.syncAsByte(_skills[idx]); + + // Synchronize character awards + for (int idx = 0; idx < 64; ++idx) { + byte b = (_awards[idx] ? 1 : 0) | (_awards[idx + 64] ? 0x10 : 0); + s.syncAsByte(b); + if (s.isLoading()) { + _awards[idx] = (b & 0xF) != 0; + _awards[idx + 64] = (b & 0xF0) != 0; + } + } + + // Synchronize spell list + for (int i = 0; i < MAX_SPELLS_PER_CLASS - 1; ++i) + s.syncAsByte(_spells[i]); + s.syncAsByte(_lloydMap); + s.syncAsByte(_lloydPosition.x); + s.syncAsByte(_lloydPosition.y); + s.syncAsByte(_hasSpells); + s.syncAsByte(_currentSpell); + s.syncAsByte(_quickOption); + + for (int i = 0; i < 9; ++i) + _weapons[i].synchronize(s); + for (int i = 0; i < 9; ++i) + _armor[i].synchronize(s); + for (int i = 0; i < 9; ++i) + _accessories[i].synchronize(s); + for (int i = 0; i < 9; ++i) + _misc[i].synchronize(s); + + s.syncAsByte(_lloydSide); + _fireResistence.synchronize(s); + _coldResistence.synchronize(s); + _electricityResistence.synchronize(s); + _poisonResistence.synchronize(s); + _energyResistence.synchronize(s); + _magicResistence.synchronize(s); + + for (int i = 0; i < 16; ++i) + s.syncAsByte(_conditions[i]); + + s.syncAsUint16LE(_townUnknown); + s.syncAsByte(_savedMazeId); + s.syncAsUint16LE(_currentHp); + s.syncAsUint16LE(_currentSp); + s.syncAsUint16LE(_birthYear); + s.syncAsUint32LE(_experience); + s.syncAsByte(_currentAdventuringSpell); + s.syncAsByte(_currentCombatSpell); +} + +Condition Character::worstCondition() const { + for (int cond = ERADICATED; cond >= CURSED; --cond) { + if (_conditions[cond]) + return (Condition)cond; + } + + return NO_CONDITION; +} + +int Character::getAge(bool ignoreTemp) const { + int year = MIN(Party::_vm->_party->_year - _birthYear, (uint)254); + + return ignoreTemp ? year : year + _tempAge; +} + +int Character::getMaxHP() const { + int hp = BASE_HP_BY_CLASS[_class]; + hp += statBonus(getStat(ENDURANCE)); + hp += RACE_HP_BONUSES[_race]; + if (_skills[BODYBUILDER]) + ++hp; + if (hp < 1) + hp = 1; + + hp *= getCurrentLevel(); + hp += itemScan(7); + + return MAX(hp, 0); +} + +int Character::getMaxSP() const { + int result = 0; + bool flag = false; + int amount = 0; + Attribute attrib; + Skill skill; + + if (!_hasSpells) + return 0; + + if (_class == CLASS_SORCERER || _class == CLASS_ARCHER) { + attrib = INTELLECT; + skill = PRESTIDIGITATION; + } else { + attrib = PERSONALITY; + skill = PRAYER_MASTER; + } + if (_class == CLASS_DRUID || _class == CLASS_RANGER) + skill = ASTROLOGER; + + for (;;) { + // Get the base number of spell points + result = statBonus(getStat(attrib)) + 3; + result += RACE_SP_BONUSES[_race][attrib - 1]; + + if (_skills[skill]) + result += 2; + if (result < 1) + result = 1; + + // Multiply it by the character's level + result *= getCurrentLevel(); + + // Classes other than sorcerer, clerics, and druids only get half the SP + if (_class != CLASS_SORCERER && _class != CLASS_CLERIC && _class != CLASS_DRUID) + result /= 2; + + if (flag || (_class != CLASS_DRUID && _class != CLASS_RANGER)) + break; + + // Druids and rangers get bonuses averaged on both personality and intellect + attrib = INTELLECT; + flag = true; + amount = result; + } + if (flag) + result = (amount + result) / 2; + + result += itemScan(8); + if (result < 0) + result = 0; + + return result; +} + +/** + * Get the effective value of a given stat for the character + */ +uint Character::getStat(Attribute attrib, bool baseOnly) const { + AttributePair attr; + int mode = 0; + + switch (attrib) { + case MIGHT: + attr = _might; + break; + case INTELLECT: + attr = _intellect; + mode = 1; + break; + case PERSONALITY: + attr = _personality; + mode = 1; + break; + case ENDURANCE: + attr = _endurance; + break; + case SPEED: + attr = _speed; + break; + case ACCURACY: + attr = _accuracy; + break; + case LUCK: + attr = _luck; + mode = 2; + break; + default: + return 0; + } + + // All the attributes except luck are affected by the character's age + if (mode < 2) { + int age = getAge(false); + int ageIndex = 0; + while (AGE_RANGES[ageIndex] <= age) + ++ageIndex; + + attr._permanent += AGE_RANGES_ADJUST[mode][ageIndex]; + } + + + attr._permanent += itemScan((int)attrib); + + if (!baseOnly) { + attr._permanent += conditionMod(attrib); + attr._permanent += attr._temporary; + } + + return MAX(attr._permanent, (uint)0); +} + +/** + * Return the color number to use for a given stat value in the character + * info or quick reference dialogs + */ +int Character::statColor(int amount, int threshold) { + if (amount < 1) + return 6; + else if (amount > threshold) + return 2; + else if (amount == threshold) + return 15; + else if (amount <= (threshold / 4)) + return 9; + else + return 32; +} + +int Character::statBonus(uint statValue) const { + int idx; + for (idx = 0; STAT_VALUES[idx] <= statValue; ++idx) + ; + + return STAT_BONUSES[idx]; +} + +bool Character::charSavingThrow(DamageType attackType) const { + int v, vMax; + + if (attackType == DT_PHYSICAL) { + v = statBonus(getStat(LUCK)) + getCurrentLevel(); + vMax = v + 20; + } else { + switch (attackType) { + case DT_MAGICAL: + v = _magicResistence._permanent + _magicResistence._temporary + itemScan(16); + break; + case DT_FIRE: + v = _fireResistence._permanent + _fireResistence._temporary + itemScan(11); + break; + case DT_ELECTRICAL: + v = _electricityResistence._permanent + _electricityResistence._temporary + itemScan(12); + break; + case DT_COLD: + v = _coldResistence._permanent + _coldResistence._temporary + itemScan(13); + break; + case DT_POISON: + v = _poisonResistence._permanent + _poisonResistence._temporary + itemScan(14); + break; + case DT_ENERGY: + v = _energyResistence._permanent + _energyResistence._temporary + itemScan(15); + break; + default: + v = 0; + break; + } + + vMax = v + 40; + } + + return Party::_vm->getRandomNumber(1, vMax) <= v; +} + +bool Character::noActions() { + Condition condition = worstCondition(); + + switch (condition) { + case CURSED: + case POISONED: + case DISEASED: + case INSANE: + case IN_LOVE: + case DRUNK: { + Common::String msg = Common::String::format(IN_NO_CONDITION, _name.c_str()); + ErrorScroll::show(Party::_vm, msg, + Party::_vm->_mode == 17 ? WT_2 : WT_NONFREEZED_WAIT); + return true; + } + default: + return false; + } +} + +void Character::setAward(int awardId, bool value) { + int v = awardId; + if (awardId == 73) + v = 126; + else if (awardId == 81) + v = 127; + + _awards[v] = value; +} + +bool Character::hasAward(int awardId) const { + int v = awardId; + if (awardId == 73) + v = 126; + else if (awardId == 81) + v = 127; + + return _awards[v]; +} + +int Character::getArmorClass(bool baseOnly) const { + Party &party = *Party::_vm->_party; + + int result = statBonus(getStat(SPEED)) + itemScan(9); + if (!baseOnly) + result += party._blessed + _ACTemp; + + return MAX(result, 0); +} + +/** + * Returns the thievery skill level, adjusted by class and race + */ +int Character::getThievery() const { + int result = getCurrentLevel() * 2; + + if (_class == CLASS_NINJA) + result += 15; + else if (_class == CLASS_ROBBER) + result += 30; + + switch (_race) { + case ELF: + case GNOME: + result += 10; + break; + case DWARF: + result += 5; + break; + case HALF_ORC: + result -= 10; + break; + default: + break; + } + + result += itemScan(10); + + // If the character doesn't have a thievery skill, then do'nt allow any result + if (!_skills[THIEVERY]) + result = 0; + + return MAX(result, 0); +} + +uint Character::getCurrentLevel() const { + return MAX(_level._permanent + _level._temporary, (uint)0); +} + +int Character::itemScan(int itemId) const { + int result = 0; + + for (int accessIdx = 0; accessIdx < 3; ++accessIdx) { + switch (accessIdx) { + case 0: + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + const XeenItem &item = _weapons[idx]; + + if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11 + && itemId != 3 && item._material >= 59 && item._material <= 130) { + int mIndex = item.getAttributeCategory(); + if (mIndex > 2) + ++mIndex; + + if (mIndex == itemId) + result += ATTRIBUTE_BONUSES[item._material - 59]; + } + } + break; + + case 1: + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + const XeenItem &item = _armor[idx]; + + if (item._frame && !(item._bonusFlags & 0xC0)) { + if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) { + int mIndex = item.getAttributeCategory(); + if (mIndex > 2) + ++mIndex; + + if (mIndex == itemId) + result += ATTRIBUTE_BONUSES[item._material - 59]; + } + + if (itemId > 10 && item._material < 37) { + int mIndex = item.getElementalCategory() + 11; + + if (mIndex == itemId) { + result += ELEMENTAL_RESISTENCES[item._material]; + } + } + + if (itemId == 9) { + result += ARMOR_STRENGTHS[item._id]; + + if (item._material >= 37 && item._material <= 58) + result += METAL_LAC[item._material - 37]; + } + } + } + break; + + case 2: + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + const XeenItem &item = _accessories[idx]; + + if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11 && itemId != 3) { + if (item._material >= 59 && item._material <= 130) { + int mIndex = item.getAttributeCategory(); + if (mIndex > 2) + ++mIndex; + + if (mIndex == itemId) { + result += ATTRIBUTE_BONUSES[item._material - 59]; + } + } + + if (itemId > 10 && item._material < 37) { + int mIndex = item.getElementalCategory() + 11; + + if (mIndex == itemId) + result += ELEMENTAL_RESISTENCES[item._material]; + } + } + } + break; + } + }; + + return result; +} + +/** + * Modifies a passed attribute value based on player's condition + */ +int Character::conditionMod(Attribute attrib) const { + if (_conditions[DEAD] || _conditions[STONED] || _conditions[ERADICATED]) + return 0; + + int v[7]; + Common::fill(&v[0], &v[7], 0); + if (_conditions[CURSED]) + v[6] -= _conditions[CURSED]; + + if (_conditions[INSANE]) { + v[2] -= _conditions[INSANE]; + v[1] -= _conditions[INSANE]; + v[5] -= _conditions[INSANE]; + v[0] -= _conditions[INSANE]; + v[4] -= _conditions[INSANE]; + } + + if (_conditions[POISONED]) { + v[0] -= _conditions[POISONED]; + v[4] -= _conditions[POISONED]; + v[5] -= _conditions[POISONED]; + } + + if (_conditions[DISEASED]) { + v[3] -= _conditions[DISEASED]; + v[2] -= _conditions[DISEASED]; + v[1] -= _conditions[DISEASED]; + } + + for (int idx = 0; idx < 7; ++idx) { + v[idx] -= _conditions[HEART_BROKEN]; + v[idx] -= _conditions[IN_LOVE]; + v[idx] -= _conditions[WEAK]; + v[idx] -= _conditions[DRUNK]; + } + + return v[attrib]; +} + +void Character::setValue(int id, uint value) { + Party &party = *Party::_vm->_party; + Scripts &scripts = *Party::_vm->_scripts; + + switch (id) { + case 3: + // Set character sex + _sex = (Sex)value; + break; + case 4: + // Set race + _race = (Race)value; + break; + case 5: + // Set class + _class = (CharacterClass)value; + break; + case 8: + // Set the current Hp + _currentHp = value; + break; + case 9: + // Set the current Sp + _currentSp = value; + break; + case 10: + case 77: + // Set temporary armor class + _ACTemp = value; + break; + case 11: + // Set temporary level + _level._temporary = value; + break; + case 12: + // Set the character's temporary age + _tempAge = value; + break; + case 16: + // Set character experience + _experience = value; + break; + case 17: + // Set party poison resistence + party._poisonResistence = value; + break; + case 18: + // Set condition + if (value == 16) { + // Clear all the conditions + Common::fill(&_conditions[CURSED], &_conditions[NO_CONDITION], false); + } else if (value == 6) { + _conditions[value] = 1; + } else { + ++_conditions[value]; + } + + if (value >= DEAD && value <= ERADICATED && _currentHp > 0) + _currentHp = 0; + break; + case 25: + // Set time of day in minutes (0-1440) + party._minutes = value; + break; + case 34: + // Set party gold + party._gold = value; + break; + case 35: + // Set party gems + party._gems = value; + break; + case 37: + _might._temporary = value; + break; + case 38: + _intellect._temporary = value; + break; + case 39: + _personality._temporary = value; + break; + case 40: + _endurance._temporary = value; + break; + case 41: + _speed._temporary = value; + break; + case 42: + _accuracy._temporary = value; + break; + case 43: + _luck._temporary = value; + break; + case 45: + _might._permanent = value; + break; + case 46: + _intellect._permanent = value; + break; + case 47: + _personality._permanent = value; + break; + case 48: + _endurance._permanent = value; + break; + case 49: + _speed._permanent = value; + break; + case 50: + _accuracy._permanent = value; + break; + case 51: + _luck._permanent = value; + break; + case 52: + _fireResistence._permanent = value; + break; + case 53: + _electricityResistence._permanent = value; + break; + case 54: + _coldResistence._permanent = value; + break; + case 55: + _poisonResistence._permanent = value; + break; + case 56: + _energyResistence._permanent = value; + break; + case 57: + _magicResistence._permanent = value; + break; + case 58: + _fireResistence._temporary = value; + break; + case 59: + _electricityResistence._temporary = value; + break; + case 60: + _coldResistence._temporary = value; + break; + case 61: + _poisonResistence._temporary = value; + break; + case 62: + _energyResistence._temporary = value; + break; + case 63: + _magicResistence._temporary = value; + break; + case 64: + _level._permanent = value; + break; + case 65: + // Set party food + party._food = value; + break; + case 69: + // Set levitate active + party._levitateActive = value != 0; + break; + case 70: + party._lightCount = value; + break; + case 71: + party._fireResistence = value; + break; + case 72: + party._electricityResistence = value; + break; + case 73: + party._coldResistence = value; + break; + case 74: + party._walkOnWaterActive = value != 0; + party._poisonResistence = value; + party._wizardEyeActive = value != 0; + party._coldResistence = value; + party._electricityResistence = value; + party._fireResistence = value; + party._lightCount = value; + party._levitateActive = value != 0; + break; + case 76: + // Set day of the year (0-99) + party._day = value; + break; + case 79: + party._wizardEyeActive = true; + break; + case 83: + scripts._nEdamageType = value; + break; + case 84: + party._mazeDirection = (Direction)value; + break; + case 85: + party._year = value; + break; + case 94: + party._walkOnWaterActive = value != 0; + break; + default: + break; + } +} + +bool Character::guildMember() const { + Party &party = *Party::_vm->_party; + + if (party._mazeId == 49 && !Party::_vm->_files->_isDarkCc) { + return hasAward(5); + } + + switch (party._mazeId) { + case 29: + return hasAward(83); + case 31: + return hasAward(84); + case 33: + return hasAward(85); + case 35: + return hasAward(86); + default: + return hasAward(87); + } +} + +uint Character::experienceToNextLevel() const { + uint next = nextExperienceLevel(); + uint curr = getCurrentExperience(); + return (curr >= next) ? 0 : next - curr; +} + +uint Character::nextExperienceLevel() const { + int shift, base; + if (_level._permanent >= 12) { + base = _level._permanent - 12; + shift = 10; + } else { + base = 0; + shift = _level._permanent - 1; + } + + return (base * 1024000) + (CLASS_EXP_LEVELS[_class] << shift); +} + +uint Character::getCurrentExperience() const { + int lev = _level._permanent - 1; + int shift, base; + + if (lev > 0 && lev < 12) + return _experience; + + if (lev >= 12) { + base = lev - 12; + shift = 10; + } else { + base = 0; + shift = lev - 1; + } + + return (base * 1024000) + (CLASS_EXP_LEVELS[_class] << shift) + + _experience; +} + + +int Character::getNumSkills() const { + int total = 0; + for (int idx = THIEVERY; idx <= DANGER_SENSE; ++idx) { + if (_skills[idx]) + ++total; + } + + return total; +} + +int Character::getNumAwards() const { + int total = 0; + for (int idx = 0; idx < 88; ++idx) { + if (hasAward(idx)) + ++total; + } + + return total; +} + +/** + * Assembles a full lines description for a specified item for use in + * the Items dialog + */ +Common::String Character::assembleItemName(int itemIndex, int displayNum, + ItemCategory category) { + Spells &spells = *Party::_vm->_spells; + + switch (category) { + case CATEGORY_WEAPON: { + // Weapons + XeenItem &i = _weapons[itemIndex]; + return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum, + !i._bonusFlags ? spells._maeNames[i._material] : "", + (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", + (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + WEAPON_NAMES[i._id], + !i._bonusFlags ? "" : BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK], + (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || + !i._bonusFlags ? "\b " : "" + ); + } + + case CATEGORY_ARMOR: { + // Armor + XeenItem &i = _armor[itemIndex]; + return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, + !i._bonusFlags ? "" : spells._maeNames[i._material], + (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", + (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + ARMOR_NAMES[i._id], + (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || + !i._bonusFlags ? "\b " : "" + ); + } + + case CATEGORY_ACCESSORY: { + // Accessories + XeenItem &i = _accessories[itemIndex]; + return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, + !i._bonusFlags ? "" : spells._maeNames[i._material], + (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", + (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + ARMOR_NAMES[i._id], + (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || + !i._bonusFlags ? "\b " : "" + ); + } + + case CATEGORY_MISC: { + // Misc + XeenItem &i = _misc[itemIndex]; + return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, + !i._bonusFlags ? "" : spells._maeNames[i._material], + (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", + (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + ARMOR_NAMES[i._id], + (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || + !i._id ? "\b " : "" + ); + } + default: + return ""; + } +} + +} // End of namespace Xeen diff --git a/engines/xeen/character.h b/engines/xeen/character.h new file mode 100644 index 0000000000..54da44a011 --- /dev/null +++ b/engines/xeen/character.h @@ -0,0 +1,231 @@ +/* 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 XEEN_CHARACTER_H +#define XEEN_CHARACTER_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/rect.h" +#include "common/serializer.h" +#include "xeen/combat.h" + +namespace Xeen { + +#define INV_ITEMS_TOTAL 9 + +enum BonusFlags { + ITEMFLAG_BONUS_MASK = 0xBF, ITEMFLAG_CURSED = 0x40, ITEMFLAG_BROKEN = 0x80 +}; + +enum ItemCategory { + CATEGORY_WEAPON = 0, CATEGORY_ARMOR = 1, CATEGORY_ACCESSORY = 2, CATEGORY_MISC = 3 +}; + +enum Sex { MALE = 0, FEMALE = 1, YES_PLEASE = 2 }; + +enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 }; + +enum CharacterClass { + CLASS_KNIGHT = 0, CLASS_PALADIN = 1, CLASS_ARCHER = 2, CLASS_CLERIC = 3, + CLASS_SORCERER = 4, CLASS_ROBBER = 5, CLASS_NINJA = 6, CLASS_BARBARIAN = 7, + CLASS_DRUID = 8, CLASS_RANGER = 9, + CLASS_12 = 12, CLASS_15 = 15, CLASS_16 = 16 +}; + +enum Attribute { + MIGHT = 0, INTELLECT = 1, PERSONALITY = 2, ENDURANCE = 3, SPEED = 4, + ACCURACY = 5, LUCK = 6 +}; + +enum Skill { + THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3, + CARTOGRAPHER = 4, CRUSADER = 5, DIRECTION_SENSE = 6, LINGUIST = 7, + MERCHANT = 8, MOUNTAINEER = 9, NAVIGATOR = 10, PATHFINDER = 11, + PRAYER_MASTER = 12, PRESTIDIGITATION = 13, SWIMMING = 14, TRACKING = 15, + SPOT_DOORS = 16, DANGER_SENSE = 17 +}; + +enum Condition { + CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, + DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, + DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11, UNCONSCIOUS = 12, + DEAD = 13, STONED = 14, ERADICATED = 15, + NO_CONDITION = 16 +}; + +class XeenEngine; + +class XeenItem { +public: + int _material; + uint _id; + int _bonusFlags; + int _frame; +public: + XeenItem(); + + void clear(); + + void synchronize(Common::Serializer &s); + + int getElementalCategory() const; + + int getAttributeCategory() const; +}; + +class InventoryItems : public Common::Array<XeenItem> { +public: + InventoryItems(); + + void discardItem(int itemIndex); + + void equipItem(int itemIndex); + + void removeItem(int itemIndex); + + void sort(); +}; + +class InventoryItemsGroup { +private: + InventoryItems *_itemSets[4]; +public: + InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor, + InventoryItems &accessories, InventoryItems &misc); + + InventoryItems &operator[](ItemCategory category); +}; + + +class AttributePair { +public: + uint _permanent; + uint _temporary; +public: + AttributePair(); + void synchronize(Common::Serializer &s); +}; + +class Character { +private: + int conditionMod(Attribute attrib) const; +public: + Common::String _name; + Sex _sex; + Race _race; + int _xeenSide; + CharacterClass _class; + AttributePair _might; + AttributePair _intellect; + AttributePair _personality; + AttributePair _endurance; + AttributePair _speed; + AttributePair _accuracy; + AttributePair _luck; + int _ACTemp; + AttributePair _level; + uint _birthDay; + int _tempAge; + int _skills[18]; + bool _awards[128]; + int _spells[39]; + int _lloydMap; + Common::Point _lloydPosition; + bool _hasSpells; + int _currentSpell; + int _quickOption; + InventoryItemsGroup _items; + InventoryItems _weapons; + InventoryItems _armor; + InventoryItems _accessories; + InventoryItems _misc; + int _lloydSide; + AttributePair _fireResistence; + AttributePair _coldResistence; + AttributePair _electricityResistence; + AttributePair _poisonResistence; + AttributePair _energyResistence; + AttributePair _magicResistence; + int _conditions[16]; + int _townUnknown; + int _savedMazeId; + int _currentHp; + int _currentSp; + uint _birthYear; + uint32 _experience; + int _currentAdventuringSpell; + int _currentCombatSpell; +public: + Character(); + void synchronize(Common::Serializer &s); + + Condition worstCondition() const; + + int getAge(bool ignoreTemp = false) const; + + int getMaxHP() const; + + int getMaxSP() const; + + uint getStat(Attribute attrib, bool baseOnly = false) const; + + static int statColor(int amount, int threshold); + + int statBonus(uint statValue) const; + + bool charSavingThrow(DamageType attackType) const; + + bool noActions(); + + void setAward(int awardId, bool value); + + bool hasAward(int awardId) const; + + int getArmorClass(bool baseOnly = false) const; + + int getThievery() const; + + uint getCurrentLevel() const; + + int itemScan(int itemId) const; + + void setValue(int id, uint value); + + bool guildMember() const; + + uint experienceToNextLevel() const; + + uint nextExperienceLevel() const; + + uint getCurrentExperience() const; + + int getNumSkills() const; + + int getNumAwards() const; + + Common::String assembleItemName(int itemIndex, int displayNum, ItemCategory category); +}; + +} // End of namespace Xeen + +#endif /* XEEN_CHARACTER_H */ diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp index 13418262bd..b9b531db7b 100644 --- a/engines/xeen/items.cpp +++ b/engines/xeen/items.cpp @@ -25,92 +25,6 @@ namespace Xeen { -XeenItem::XeenItem() { - clear(); -} - -void XeenItem::clear() { - _material = _id = _bonusFlags = 0; - _frame = 0; -} - -void XeenItem::synchronize(Common::Serializer &s) { - s.syncAsByte(_material); - s.syncAsByte(_id); - s.syncAsByte(_bonusFlags); - s.syncAsByte(_frame); -} - -int XeenItem::getElementalCategory() const { - int idx; - for (idx = 0; ELEMENTAL_CATEGORIES[idx] < _material; ++idx) - ; - - return idx; -} - -int XeenItem::getAttributeCategory() const { - int m = _material - 59; - int idx; - for (idx = 0; ATTRIBUTE_CATEGORIES[idx] < m; ++idx) - ; - - return idx; -} - -/*------------------------------------------------------------------------*/ - -InventoryItems::InventoryItems() : Common::Array<XeenItem>((XeenItem *)nullptr, INV_ITEMS_TOTAL) { -} - -void InventoryItems::discardItem(int itemIndex) { - operator[](itemIndex).clear(); - sort(); -} - -void InventoryItems::sort() { - for (uint idx = 0; idx < size(); ++idx) { - if (operator[](idx)._id == 0) { - // Found empty slot - operator[](idx).clear(); - - // Scan through the rest of the list to find any item - for (uint idx2 = idx + 1; idx2 < size(); ++idx2) { - if (operator[](idx2)._id) { - // Found an item, so move it into the blank slot - operator[](idx) = operator[](idx2); - operator[](idx2).clear(); - break; - } - } - } - } -} - -void InventoryItems::equipItem(int itemIndex) { - error("TODO"); -} - -void InventoryItems::removeItem(int itemIndex) { - error("TODO"); -} - -/*------------------------------------------------------------------------*/ - -InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor, - InventoryItems &accessories, InventoryItems &misc) { - _itemSets[0] = &weapons; - _itemSets[1] = &armor; - _itemSets[2] = &accessories; - _itemSets[3] = &misc; -} - -InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) { - return *_itemSets[category]; -} - -/*------------------------------------------------------------------------*/ - Treasure::Treasure() { _hasItems = false; } diff --git a/engines/xeen/items.h b/engines/xeen/items.h index c0b82b9fce..1e208615f8 100644 --- a/engines/xeen/items.h +++ b/engines/xeen/items.h @@ -23,63 +23,11 @@ #ifndef XEEN_ITEMS_H #define XEEN_ITEMS_H -#include "common/scummsys.h" -#include "common/array.h" -#include "common/serializer.h" +#include "xeen/character.h" namespace Xeen { #define TOTAL_ITEMS 10 -#define INV_ITEMS_TOTAL 9 - -enum BonusFlags { - ITEMFLAG_BONUS_MASK = 0xBF, ITEMFLAG_CURSED = 0x40, ITEMFLAG_BROKEN = 0x80 -}; - -enum ItemCategory { - CATEGORY_WEAPON = 0, CATEGORY_ARMOR = 1, CATEGORY_ACCESSORY = 2, CATEGORY_MISC = 3 -}; - -class XeenItem { -public: - int _material; - uint _id; - int _bonusFlags; - int _frame; -public: - XeenItem(); - - void clear(); - - void synchronize(Common::Serializer &s); - - int getElementalCategory() const; - - int getAttributeCategory() const; -}; - -class InventoryItems : public Common::Array<XeenItem> { -public: - InventoryItems(); - - void discardItem(int itemIndex); - - void equipItem(int itemIndex); - - void removeItem(int itemIndex); - - void sort(); -}; - -class InventoryItemsGroup { -private: - InventoryItems *_itemSets[4]; -public: - InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor, - InventoryItems &accessories, InventoryItems &misc); - - InventoryItems &operator[](ItemCategory category); -}; class Treasure { public: diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index c1cdd055b8..25568523cd 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -4,6 +4,7 @@ MODULE_OBJS := \ clouds\clouds_game.o \ darkside\darkside_game.o \ worldofxeen\worldofxeen_game.o \ + character.o \ combat.o \ debugger.o \ detection.o \ diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 7d47eafaf4..be8f4e6e18 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -32,897 +32,6 @@ namespace Xeen { -AttributePair::AttributePair() { - _temporary = _permanent = 0; -} - -void AttributePair::synchronize(Common::Serializer &s) { - s.syncAsByte(_permanent); - s.syncAsByte(_temporary); -} - -/*------------------------------------------------------------------------*/ - -Character::Character(): _items(_weapons, _armor, _accessories, _misc) { - _sex = MALE; - _race = HUMAN; - _xeenSide = 0; - _class = CLASS_KNIGHT; - _ACTemp = 0; - _birthDay = 0; - _tempAge = 0; - Common::fill(&_skills[0], &_skills[18], 0); - Common::fill(&_awards[0], &_awards[128], false); - Common::fill(&_spells[0], &_spells[39], 0); - _lloydMap = 0; - _hasSpells = false; - _currentSpell = 0; - _quickOption = 0; - _lloydSide = 0; - Common::fill(&_conditions[0], &_conditions[16], 0); - _townUnknown = 0; - _savedMazeId = 0; - _currentHp = 0; - _currentSp = 0; - _birthYear = 0; - _experience = 0; - _currentAdventuringSpell = 0; - _currentCombatSpell = 0; -} - -void Character::synchronize(Common::Serializer &s) { - char name[16]; - Common::fill(&name[0], &name[16], '\0'); - strncpy(name, _name.c_str(), 16); - s.syncBytes((byte *)name, 16); - - if (s.isLoading()) - _name = Common::String(name); - - s.syncAsByte(_sex); - s.syncAsByte(_race); - s.syncAsByte(_xeenSide); - s.syncAsByte(_class); - - _might.synchronize(s); - _intellect.synchronize(s); - _personality.synchronize(s); - _endurance.synchronize(s); - _speed.synchronize(s); - _accuracy.synchronize(s); - _luck.synchronize(s); - s.syncAsByte(_ACTemp); - _level.synchronize(s); - s.syncAsByte(_birthDay); - s.syncAsByte(_tempAge); - - // Synchronize the skill list - for (int idx = 0; idx < 18; ++idx) - s.syncAsByte(_skills[idx]); - - // Synchronize character awards - for (int idx = 0; idx < 64; ++idx) { - byte b = (_awards[idx] ? 1 : 0) | (_awards[idx + 64] ? 0x10 : 0); - s.syncAsByte(b); - if (s.isLoading()) { - _awards[idx] = (b & 0xF) != 0; - _awards[idx + 64] = (b & 0xF0) != 0; - } - } - - // Synchronize spell list - for (int i = 0; i < MAX_SPELLS_PER_CLASS - 1; ++i) - s.syncAsByte(_spells[i]); - s.syncAsByte(_lloydMap); - s.syncAsByte(_lloydPosition.x); - s.syncAsByte(_lloydPosition.y); - s.syncAsByte(_hasSpells); - s.syncAsByte(_currentSpell); - s.syncAsByte(_quickOption); - - for (int i = 0; i < 9; ++i) - _weapons[i].synchronize(s); - for (int i = 0; i < 9; ++i) - _armor[i].synchronize(s); - for (int i = 0; i < 9; ++i) - _accessories[i].synchronize(s); - for (int i = 0; i < 9; ++i) - _misc[i].synchronize(s); - - s.syncAsByte(_lloydSide); - _fireResistence.synchronize(s); - _coldResistence.synchronize(s); - _electricityResistence.synchronize(s); - _poisonResistence.synchronize(s); - _energyResistence.synchronize(s); - _magicResistence.synchronize(s); - - for (int i = 0; i < 16; ++i) - s.syncAsByte(_conditions[i]); - - s.syncAsUint16LE(_townUnknown); - s.syncAsByte(_savedMazeId); - s.syncAsUint16LE(_currentHp); - s.syncAsUint16LE(_currentSp); - s.syncAsUint16LE(_birthYear); - s.syncAsUint32LE(_experience); - s.syncAsByte(_currentAdventuringSpell); - s.syncAsByte(_currentCombatSpell); -} - -Condition Character::worstCondition() const { - for (int cond = ERADICATED; cond >= CURSED; --cond) { - if (_conditions[cond]) - return (Condition)cond; - } - - return NO_CONDITION; -} - -int Character::getAge(bool ignoreTemp) const { - int year = MIN(Party::_vm->_party->_year - _birthYear, (uint)254); - - return ignoreTemp ? year : year + _tempAge; -} - -int Character::getMaxHP() const { - int hp = BASE_HP_BY_CLASS[_class]; - hp += statBonus(getStat(ENDURANCE)); - hp += RACE_HP_BONUSES[_race]; - if (_skills[BODYBUILDER]) - ++hp; - if (hp < 1) - hp = 1; - - hp *= getCurrentLevel(); - hp += itemScan(7); - - return MAX(hp, 0); -} - -int Character::getMaxSP() const { - int result = 0; - bool flag = false; - int amount = 0; - Attribute attrib; - Skill skill; - - if (!_hasSpells) - return 0; - - if (_class == CLASS_SORCERER || _class == CLASS_ARCHER) { - attrib = INTELLECT; - skill = PRESTIDIGITATION; - } else { - attrib = PERSONALITY; - skill = PRAYER_MASTER; - } - if (_class == CLASS_DRUID || _class == CLASS_RANGER) - skill = ASTROLOGER; - - for (;;) { - // Get the base number of spell points - result = statBonus(getStat(attrib)) + 3; - result += RACE_SP_BONUSES[_race][attrib - 1]; - - if (_skills[skill]) - result += 2; - if (result < 1) - result = 1; - - // Multiply it by the character's level - result *= getCurrentLevel(); - - // Classes other than sorcerer, clerics, and druids only get half the SP - if (_class != CLASS_SORCERER && _class != CLASS_CLERIC && _class != CLASS_DRUID) - result /= 2; - - if (flag || (_class != CLASS_DRUID && _class != CLASS_RANGER)) - break; - - // Druids and rangers get bonuses averaged on both personality and intellect - attrib = INTELLECT; - flag = true; - amount = result; - } - if (flag) - result = (amount + result) / 2; - - result += itemScan(8); - if (result < 0) - result = 0; - - return result; -} - -/** - * Get the effective value of a given stat for the character - */ -uint Character::getStat(Attribute attrib, bool baseOnly) const { - AttributePair attr; - int mode = 0; - - switch (attrib) { - case MIGHT: - attr = _might; - break; - case INTELLECT: - attr = _intellect; - mode = 1; - break; - case PERSONALITY: - attr = _personality; - mode = 1; - break; - case ENDURANCE: - attr = _endurance; - break; - case SPEED: - attr = _speed; - break; - case ACCURACY: - attr = _accuracy; - break; - case LUCK: - attr = _luck; - mode = 2; - break; - default: - return 0; - } - - // All the attributes except luck are affected by the character's age - if (mode < 2) { - int age = getAge(false); - int ageIndex = 0; - while (AGE_RANGES[ageIndex] <= age) - ++ageIndex; - - attr._permanent += AGE_RANGES_ADJUST[mode][ageIndex]; - } - - - attr._permanent += itemScan((int)attrib); - - if (!baseOnly) { - attr._permanent += conditionMod(attrib); - attr._permanent += attr._temporary; - } - - return MAX(attr._permanent, (uint)0); -} - -/** - * Return the color number to use for a given stat value in the character - * info or quick reference dialogs - */ -int Character::statColor(int amount, int threshold) { - if (amount < 1) - return 6; - else if (amount > threshold) - return 2; - else if (amount == threshold) - return 15; - else if (amount <= (threshold / 4)) - return 9; - else - return 32; -} - -int Character::statBonus(uint statValue) const { - int idx; - for (idx = 0; STAT_VALUES[idx] <= statValue; ++idx) - ; - - return STAT_BONUSES[idx]; -} - -bool Character::charSavingThrow(DamageType attackType) const { - int v, vMax; - - if (attackType == DT_PHYSICAL) { - v = statBonus(getStat(LUCK)) + getCurrentLevel(); - vMax = v + 20; - } else { - switch (attackType) { - case DT_MAGICAL: - v = _magicResistence._permanent + _magicResistence._temporary + itemScan(16); - break; - case DT_FIRE: - v = _fireResistence._permanent + _fireResistence._temporary + itemScan(11); - break; - case DT_ELECTRICAL: - v = _electricityResistence._permanent + _electricityResistence._temporary + itemScan(12); - break; - case DT_COLD: - v = _coldResistence._permanent + _coldResistence._temporary + itemScan(13); - break; - case DT_POISON: - v = _poisonResistence._permanent + _poisonResistence._temporary + itemScan(14); - break; - case DT_ENERGY: - v = _energyResistence._permanent + _energyResistence._temporary + itemScan(15); - break; - default: - v = 0; - break; - } - - vMax = v + 40; - } - - return Party::_vm->getRandomNumber(1, vMax) <= v; -} - -bool Character::noActions() { - Condition condition = worstCondition(); - - switch (condition) { - case CURSED: - case POISONED: - case DISEASED: - case INSANE: - case IN_LOVE: - case DRUNK: { - Common::String msg = Common::String::format(IN_NO_CONDITION, _name.c_str()); - ErrorScroll::show(Party::_vm, msg, - Party::_vm->_mode == 17 ? WT_2 : WT_NONFREEZED_WAIT); - return true; - } - default: - return false; - } -} - -void Character::setAward(int awardId, bool value) { - int v = awardId; - if (awardId == 73) - v = 126; - else if (awardId == 81) - v = 127; - - _awards[v] = value; -} - -bool Character::hasAward(int awardId) const { - int v = awardId; - if (awardId == 73) - v = 126; - else if (awardId == 81) - v = 127; - - return _awards[v]; -} - -int Character::getArmorClass(bool baseOnly) const { - Party &party = *Party::_vm->_party; - - int result = statBonus(getStat(SPEED)) + itemScan(9); - if (!baseOnly) - result += party._blessed + _ACTemp; - - return MAX(result, 0); -} - -/** - * Returns the thievery skill level, adjusted by class and race - */ -int Character::getThievery() const { - int result = getCurrentLevel() * 2; - - if (_class == CLASS_NINJA) - result += 15; - else if (_class == CLASS_ROBBER) - result += 30; - - switch (_race) { - case ELF: - case GNOME: - result += 10; - break; - case DWARF: - result += 5; - break; - case HALF_ORC: - result -= 10; - break; - default: - break; - } - - result += itemScan(10); - - // If the character doesn't have a thievery skill, then do'nt allow any result - if (!_skills[THIEVERY]) - result = 0; - - return MAX(result, 0); -} - -uint Character::getCurrentLevel() const { - return MAX(_level._permanent + _level._temporary, (uint)0); -} - -int Character::itemScan(int itemId) const { - int result = 0; - - for (int accessIdx = 0; accessIdx < 3; ++accessIdx) { - switch (accessIdx) { - case 0: - for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { - const XeenItem &item = _weapons[idx]; - - if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11 - && itemId != 3 && item._material >= 59 && item._material <= 130) { - int mIndex = item.getAttributeCategory(); - if (mIndex > 2) - ++mIndex; - - if (mIndex == itemId) - result += ATTRIBUTE_BONUSES[item._material - 59]; - } - } - break; - - case 1: - for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { - const XeenItem &item = _armor[idx]; - - if (item._frame && !(item._bonusFlags & 0xC0)) { - if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) { - int mIndex = item.getAttributeCategory(); - if (mIndex > 2) - ++mIndex; - - if (mIndex == itemId) - result += ATTRIBUTE_BONUSES[item._material - 59]; - } - - if (itemId > 10 && item._material < 37) { - int mIndex = item.getElementalCategory() + 11; - - if (mIndex == itemId) { - result += ELEMENTAL_RESISTENCES[item._material]; - } - } - - if (itemId == 9) { - result += ARMOR_STRENGTHS[item._id]; - - if (item._material >= 37 && item._material <= 58) - result += METAL_LAC[item._material - 37]; - } - } - } - break; - - case 2: - for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { - const XeenItem &item = _accessories[idx]; - - if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11 && itemId != 3) { - if (item._material >= 59 && item._material <= 130) { - int mIndex = item.getAttributeCategory(); - if (mIndex > 2) - ++mIndex; - - if (mIndex == itemId) { - result += ATTRIBUTE_BONUSES[item._material - 59]; - } - } - - if (itemId > 10 && item._material < 37) { - int mIndex = item.getElementalCategory() + 11; - - if (mIndex == itemId) - result += ELEMENTAL_RESISTENCES[item._material]; - } - } - } - break; - } - }; - - return result; -} - -/** - * Modifies a passed attribute value based on player's condition - */ -int Character::conditionMod(Attribute attrib) const { - if (_conditions[DEAD] || _conditions[STONED] || _conditions[ERADICATED]) - return 0; - - int v[7]; - Common::fill(&v[0], &v[7], 0); - if (_conditions[CURSED]) - v[6] -= _conditions[CURSED]; - - if (_conditions[INSANE]) { - v[2] -= _conditions[INSANE]; - v[1] -= _conditions[INSANE]; - v[5] -= _conditions[INSANE]; - v[0] -= _conditions[INSANE]; - v[4] -= _conditions[INSANE]; - } - - if (_conditions[POISONED]) { - v[0] -= _conditions[POISONED]; - v[4] -= _conditions[POISONED]; - v[5] -= _conditions[POISONED]; - } - - if (_conditions[DISEASED]) { - v[3] -= _conditions[DISEASED]; - v[2] -= _conditions[DISEASED]; - v[1] -= _conditions[DISEASED]; - } - - for (int idx = 0; idx < 7; ++idx) { - v[idx] -= _conditions[HEART_BROKEN]; - v[idx] -= _conditions[IN_LOVE]; - v[idx] -= _conditions[WEAK]; - v[idx] -= _conditions[DRUNK]; - } - - return v[attrib]; -} - -void Character::setValue(int id, uint value) { - Party &party = *Party::_vm->_party; - Scripts &scripts = *Party::_vm->_scripts; - - switch (id) { - case 3: - // Set character sex - _sex = (Sex)value; - break; - case 4: - // Set race - _race = (Race)value; - break; - case 5: - // Set class - _class = (CharacterClass)value; - break; - case 8: - // Set the current Hp - _currentHp = value; - break; - case 9: - // Set the current Sp - _currentSp = value; - break; - case 10: - case 77: - // Set temporary armor class - _ACTemp = value; - break; - case 11: - // Set temporary level - _level._temporary = value; - break; - case 12: - // Set the character's temporary age - _tempAge = value; - break; - case 16: - // Set character experience - _experience = value; - break; - case 17: - // Set party poison resistence - party._poisonResistence = value; - break; - case 18: - // Set condition - if (value == 16) { - // Clear all the conditions - Common::fill(&_conditions[CURSED], &_conditions[NO_CONDITION], false); - } else if (value == 6) { - _conditions[value] = 1; - } else { - ++_conditions[value]; - } - - if (value >= DEAD && value <= ERADICATED && _currentHp > 0) - _currentHp = 0; - break; - case 25: - // Set time of day in minutes (0-1440) - party._minutes = value; - break; - case 34: - // Set party gold - party._gold = value; - break; - case 35: - // Set party gems - party._gems = value; - break; - case 37: - _might._temporary = value; - break; - case 38: - _intellect._temporary = value; - break; - case 39: - _personality._temporary = value; - break; - case 40: - _endurance._temporary = value; - break; - case 41: - _speed._temporary = value; - break; - case 42: - _accuracy._temporary = value; - break; - case 43: - _luck._temporary = value; - break; - case 45: - _might._permanent = value; - break; - case 46: - _intellect._permanent = value; - break; - case 47: - _personality._permanent = value; - break; - case 48: - _endurance._permanent = value; - break; - case 49: - _speed._permanent = value; - break; - case 50: - _accuracy._permanent = value; - break; - case 51: - _luck._permanent = value; - break; - case 52: - _fireResistence._permanent = value; - break; - case 53: - _electricityResistence._permanent = value; - break; - case 54: - _coldResistence._permanent = value; - break; - case 55: - _poisonResistence._permanent = value; - break; - case 56: - _energyResistence._permanent = value; - break; - case 57: - _magicResistence._permanent = value; - break; - case 58: - _fireResistence._temporary = value; - break; - case 59: - _electricityResistence._temporary = value; - break; - case 60: - _coldResistence._temporary = value; - break; - case 61: - _poisonResistence._temporary = value; - break; - case 62: - _energyResistence._temporary = value; - break; - case 63: - _magicResistence._temporary = value; - break; - case 64: - _level._permanent = value; - break; - case 65: - // Set party food - party._food = value; - break; - case 69: - // Set levitate active - party._levitateActive = value != 0; - break; - case 70: - party._lightCount = value; - break; - case 71: - party._fireResistence = value; - break; - case 72: - party._electricityResistence = value; - break; - case 73: - party._coldResistence = value; - break; - case 74: - party._walkOnWaterActive = value != 0; - party._poisonResistence = value; - party._wizardEyeActive = value != 0; - party._coldResistence = value; - party._electricityResistence = value; - party._fireResistence = value; - party._lightCount = value; - party._levitateActive = value != 0; - break; - case 76: - // Set day of the year (0-99) - party._day = value; - break; - case 79: - party._wizardEyeActive = true; - break; - case 83: - scripts._nEdamageType = value; - break; - case 84: - party._mazeDirection = (Direction)value; - break; - case 85: - party._year = value; - break; - case 94: - party._walkOnWaterActive = value != 0; - break; - default: - break; - } -} - -bool Character::guildMember() const { - Party &party = *Party::_vm->_party; - - if (party._mazeId == 49 && !Party::_vm->_files->_isDarkCc) { - return hasAward(5); - } - - switch (party._mazeId) { - case 29: - return hasAward(83); - case 31: - return hasAward(84); - case 33: - return hasAward(85); - case 35: - return hasAward(86); - default: - return hasAward(87); - } -} - -uint Character::experienceToNextLevel() const { - uint next = nextExperienceLevel(); - uint curr = getCurrentExperience(); - return (curr >= next) ? 0 : next - curr; -} - -uint Character::nextExperienceLevel() const { - int shift, base; - if (_level._permanent >= 12) { - base = _level._permanent - 12; - shift = 10; - } else { - base = 0; - shift = _level._permanent - 1; - } - - return (base * 1024000) + (CLASS_EXP_LEVELS[_class] << shift); -} - -uint Character::getCurrentExperience() const { - int lev = _level._permanent - 1; - int shift, base; - - if (lev > 0 && lev < 12) - return _experience; - - if (lev >= 12) { - base = lev - 12; - shift = 10; - } else { - base = 0; - shift = lev - 1; - } - - return (base * 1024000) + (CLASS_EXP_LEVELS[_class] << shift) + - _experience; -} - - -int Character::getNumSkills() const { - int total = 0; - for (int idx = THIEVERY; idx <= DANGER_SENSE; ++idx) { - if (_skills[idx]) - ++total; - } - - return total; -} - -int Character::getNumAwards() const { - int total = 0; - for (int idx = 0; idx < 88; ++idx) { - if (hasAward(idx)) - ++total; - } - - return total; -} - -/** - * Assembles a full lines description for a specified item for use in - * the Items dialog - */ -Common::String Character::assembleItemName(int itemIndex, int displayNum, - ItemCategory category) { - Spells &spells = *Party::_vm->_spells; - - switch (category) { - case CATEGORY_WEAPON: { - // Weapons - XeenItem &i = _weapons[itemIndex]; - return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum, - !i._bonusFlags ? spells._maeNames[i._material] : "", - (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", - (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", - WEAPON_NAMES[i._id], - !i._bonusFlags ? "" : BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK], - (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || - !i._bonusFlags ? "\b " : "" - ); - } - - case CATEGORY_ARMOR: { - // Armor - XeenItem &i = _armor[itemIndex]; - return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, - !i._bonusFlags ? "" : spells._maeNames[i._material], - (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", - (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", - ARMOR_NAMES[i._id], - (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || - !i._bonusFlags ? "\b " : "" - ); - } - - case CATEGORY_ACCESSORY: { - // Accessories - XeenItem &i = _accessories[itemIndex]; - return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, - !i._bonusFlags ? "" : spells._maeNames[i._material], - (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", - (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", - ARMOR_NAMES[i._id], - (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || - !i._bonusFlags ? "\b " : "" - ); - } - - case CATEGORY_MISC: { - // Misc - XeenItem &i = _misc[itemIndex]; - return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, - !i._bonusFlags ? "" : spells._maeNames[i._material], - (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", - (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", - ARMOR_NAMES[i._id], - (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || - !i._id ? "\b " : "" - ); - } - default: - return ""; - } -} - -/*------------------------------------------------------------------------*/ - void Roster::synchronize(Common::Serializer &s) { if (s.isLoading()) resize(30); diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 73de7065aa..138ecba2d4 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -39,153 +39,12 @@ enum Direction { enum Difficulty { ADVENTURER = 0, WARRIOR = 1 }; -enum Sex { MALE = 0, FEMALE = 1, YES_PLEASE = 2 }; - -enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 }; - -enum CharacterClass { - CLASS_KNIGHT = 0, CLASS_PALADIN = 1, CLASS_ARCHER = 2, CLASS_CLERIC = 3, - CLASS_SORCERER = 4, CLASS_ROBBER = 5, CLASS_NINJA = 6, CLASS_BARBARIAN = 7, - CLASS_DRUID = 8, CLASS_RANGER = 9, - CLASS_12 = 12, CLASS_15 = 15, CLASS_16 = 16 -}; - -enum Attribute{ - MIGHT = 0, INTELLECT = 1, PERSONALITY = 2, ENDURANCE = 3, SPEED = 4, - ACCURACY = 5, LUCK = 6 -}; - -enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3, - CARTOGRAPHER = 4, CRUSADER = 5, DIRECTION_SENSE = 6, LINGUIST = 7, - MERCHANT = 8, MOUNTAINEER = 9, NAVIGATOR = 10, PATHFINDER = 11, - PRAYER_MASTER = 12, PRESTIDIGITATION = 13, SWIMMING = 14, TRACKING = 15, - SPOT_DOORS = 16, DANGER_SENSE = 17 -}; - -enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, - DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, - DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11, UNCONSCIOUS = 12, - DEAD = 13, STONED = 14, ERADICATED = 15, - NO_CONDITION = 16 -}; - #define ITEMS_COUNT 36 #define TOTAL_CHARACTERS 30 #define XEEN_TOTAL_CHARACTERS 24 #define MAX_ACTIVE_PARTY 6 #define TOTAL_STATS 7 -class XeenEngine; - -class AttributePair { -public: - uint _permanent; - uint _temporary; -public: - AttributePair(); - void synchronize(Common::Serializer &s); -}; - -class Character { -private: - int conditionMod(Attribute attrib) const; -public: - Common::String _name; - Sex _sex; - Race _race; - int _xeenSide; - CharacterClass _class; - AttributePair _might; - AttributePair _intellect; - AttributePair _personality; - AttributePair _endurance; - AttributePair _speed; - AttributePair _accuracy; - AttributePair _luck; - int _ACTemp; - AttributePair _level; - uint _birthDay; - int _tempAge; - int _skills[18]; - bool _awards[128]; - int _spells[39]; - int _lloydMap; - Common::Point _lloydPosition; - bool _hasSpells; - int _currentSpell; - int _quickOption; - InventoryItemsGroup _items; - InventoryItems _weapons; - InventoryItems _armor; - InventoryItems _accessories; - InventoryItems _misc; - int _lloydSide; - AttributePair _fireResistence; - AttributePair _coldResistence; - AttributePair _electricityResistence; - AttributePair _poisonResistence; - AttributePair _energyResistence; - AttributePair _magicResistence; - int _conditions[16]; - int _townUnknown; - int _savedMazeId; - int _currentHp; - int _currentSp; - uint _birthYear; - uint32 _experience; - int _currentAdventuringSpell; - int _currentCombatSpell; -public: - Character(); - void synchronize(Common::Serializer &s); - - Condition worstCondition() const; - - int getAge(bool ignoreTemp = false) const; - - int getMaxHP() const; - - int getMaxSP() const; - - uint getStat(Attribute attrib, bool baseOnly = false) const; - - static int statColor(int amount, int threshold); - - int statBonus(uint statValue) const; - - bool charSavingThrow(DamageType attackType) const; - - bool noActions(); - - void setAward(int awardId, bool value); - - bool hasAward(int awardId) const; - - int getArmorClass(bool baseOnly = false) const; - - int getThievery() const; - - uint getCurrentLevel() const; - - int itemScan(int itemId) const; - - void setValue(int id, uint value); - - bool guildMember() const; - - uint experienceToNextLevel() const; - - uint nextExperienceLevel() const; - - uint getCurrentExperience() const; - - int getNumSkills() const; - - int getNumAwards() const; - - Common::String assembleItemName(int itemIndex, int displayNum, ItemCategory category); -}; - class Roster: public Common::Array<Character> { public: Roster() {} -- cgit v1.2.3 From 7ea32f3333cb2123675f6dbdfae3ed232347d1a5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 4 Feb 2015 20:41:17 -0500 Subject: XEEN: Moved passRestrictions to the InventoryItems class --- engines/xeen/character.cpp | 53 ++++++++++++++++++++++++++++++++++++++-- engines/xeen/character.h | 9 ++++++- engines/xeen/dialogs_items.cpp | 55 +----------------------------------------- engines/xeen/dialogs_items.h | 3 --- engines/xeen/party.h | 2 ++ 5 files changed, 62 insertions(+), 60 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index f712e78e8c..02c578a313 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -61,10 +61,56 @@ int XeenItem::getAttributeCategory() const { /*------------------------------------------------------------------------*/ -InventoryItems::InventoryItems() { +InventoryItems::InventoryItems(Character *character, ItemCategory category): + _character(character), _category(category) { resize(INV_ITEMS_TOTAL); + + static const char *const *NAMES[4] = { + WEAPON_NAMES, ARMOR_NAMES, ACCESSORY_NAMES, MISC_NAMES + }; + _names = NAMES[category]; } +/** +* Return whether a given item passes class-based usage restrictions +*/ +bool InventoryItems::passRestrictions(int itemId, bool showError) const { + CharacterClass charClass = _character->_class; + + switch (charClass) { + case CLASS_KNIGHT: + case CLASS_PALADIN: + return true; + + case CLASS_ARCHER: + case CLASS_CLERIC: + case CLASS_SORCERER: + case CLASS_ROBBER: + case CLASS_NINJA: + case CLASS_BARBARIAN: + case CLASS_DRUID: + case CLASS_RANGER: { + if (!(ITEM_RESTRICTIONS[itemId + RESTRICTION_OFFSETS[_category]] & + (1 << (charClass - CLASS_ARCHER)))) + return true; + break; + } + + default: + break; + } + + Common::String name = _names[itemId]; + if (showError) { + Common::String msg = Common::String::format(NOT_PROFICIENT, + CLASS_NAMES[charClass], name.c_str()); + ErrorScroll::show(Party::_vm, msg, WT_FREEZE_WAIT); + } + + return false; +} + + void InventoryItems::discardItem(int itemIndex) { operator[](itemIndex).clear(); sort(); @@ -127,7 +173,10 @@ AttributePair::AttributePair() { /*------------------------------------------------------------------------*/ -Character::Character(): _items(_weapons, _armor, _accessories, _misc) { +Character::Character(): + _weapons(this, CATEGORY_WEAPON), _armor(this, CATEGORY_ARMOR), + _accessories(this, CATEGORY_ACCESSORY), _misc(this, CATEGORY_MISC), + _items(_weapons, _armor, _accessories, _misc) { _sex = MALE; _race = HUMAN; _xeenSide = 0; diff --git a/engines/xeen/character.h b/engines/xeen/character.h index 54da44a011..b3c9965e9d 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -74,6 +74,7 @@ enum Condition { }; class XeenEngine; +class Character; class XeenItem { public: @@ -94,8 +95,14 @@ public: }; class InventoryItems : public Common::Array<XeenItem> { +private: + Character *_character; + ItemCategory _category; + const char *const *_names; public: - InventoryItems(); + InventoryItems(Character *character, ItemCategory category); + + bool passRestrictions(int itemId, bool showError) const; void discardItem(int itemIndex); diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index 634fb2de39..c28085c15e 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -154,7 +154,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { DrawStruct &ds = _itemsDrawList[idx]; ds._sprites = &_equipSprites; - if (passRestrictions(c->_class, i._id, true, CATEGORY_WEAPON)) + if (c->_weapons.passRestrictions(i._id, true)) ds._frame = i._frame; else ds._frame = 14; @@ -537,59 +537,6 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode, return (mode == ITEMMODE_CHAR_INFO) ? 0 : result; } -/** - * Return whether a given item passes class-based usage restrictions - */ -bool ItemsDialog::passRestrictions(CharacterClass charClass, int itemId, - bool showError, ItemCategory category) const { - switch (charClass) { - case CLASS_KNIGHT: - case CLASS_PALADIN: - return true; - - case CLASS_ARCHER: - case CLASS_CLERIC: - case CLASS_SORCERER: - case CLASS_ROBBER: - case CLASS_NINJA: - case CLASS_BARBARIAN: - case CLASS_DRUID: - case CLASS_RANGER: { - if (!(ITEM_RESTRICTIONS[itemId + RESTRICTION_OFFSETS[category]] & - (1 << (charClass - CLASS_ARCHER)))) - return true; - break; - } - - default: - break; - } - - Common::String name; - switch (category) { - case CATEGORY_WEAPON: - name = WEAPON_NAMES[itemId]; - break; - case CATEGORY_ARMOR: - name = ARMOR_NAMES[itemId]; - break; - case CATEGORY_ACCESSORY: - name = ACCESSORY_NAMES[itemId]; - break; - case CATEGORY_MISC: - name = MISC_NAMES[itemId]; - break; - } - - if (showError) { - Common::String msg = Common::String::format(NOT_PROFICIENT, - CLASS_NAMES[charClass], name.c_str()); - ErrorScroll::show(_vm, msg, WT_FREEZE_WAIT); - } - - return false; -} - bool ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, ItemCategory category, ItemsMode mode) { Combat &combat = *_vm->_combat; diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h index c30eaa9a4a..aff43f6429 100644 --- a/engines/xeen/dialogs_items.h +++ b/engines/xeen/dialogs_items.h @@ -58,9 +58,6 @@ private: int calcItemCost(Character *c, int itemIndex, ItemsMode mode, int skillLevel, ItemCategory category); - bool passRestrictions(CharacterClass charClass, int itemId, - bool showError, ItemCategory category) const; - bool doItemOptions(Character &c, int actionIndex, int itemIndex, ItemCategory category, ItemsMode mode); public: diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 138ecba2d4..8da1163a5f 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -27,6 +27,7 @@ #include "common/array.h" #include "common/rect.h" #include "common/serializer.h" +#include "xeen/character.h" #include "xeen/combat.h" #include "xeen/dialogs_error.h" #include "xeen/items.h" @@ -54,6 +55,7 @@ public: class Party { friend class Character; + friend class InventoryItems; private: static XeenEngine *_vm; public: -- cgit v1.2.3 From a983d9abcea603a3857c1c250f398e6b2fae29a0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 4 Feb 2015 22:24:45 -0500 Subject: XEEN: Implemented weapon variation of equipItem --- engines/xeen/character.cpp | 96 ++++++++++++++++++++++++++++++++++++++++-- engines/xeen/character.h | 40 +++++++++++++++--- engines/xeen/dialogs_error.cpp | 25 +++++------ engines/xeen/dialogs_error.h | 13 ++++-- engines/xeen/resources.cpp | 5 +++ engines/xeen/resources.h | 5 +++ engines/xeen/spells.cpp | 4 +- 7 files changed, 159 insertions(+), 29 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index 02c578a313..00b7e4333f 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -21,6 +21,7 @@ */ #include "xeen/character.h" +#include "xeen/dialogs_error.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -110,12 +111,25 @@ bool InventoryItems::passRestrictions(int itemId, bool showError) const { return false; } +/** + * Return the bare name of a given inventory item + */ +Common::String InventoryItems::getName(int itemIndex) { + int id = operator[](itemIndex)._id; + return _names[id]; +} +/** + * Discard an item from the inventory + */ void InventoryItems::discardItem(int itemIndex) { operator[](itemIndex).clear(); sort(); } +/** + * Sorts the items list, removing any empty item slots to the end of the array + */ void InventoryItems::sort() { for (uint idx = 0; idx < size(); ++idx) { if (operator[](idx)._id == 0) { @@ -135,16 +149,91 @@ void InventoryItems::sort() { } } -void InventoryItems::equipItem(int itemIndex) { +void InventoryItems::removeItem(int itemIndex) { error("TODO"); } -void InventoryItems::removeItem(int itemIndex) { +void InventoryItems::equipError(int itemIndex1, ItemCategory category1, int itemIndex2, + ItemCategory category2) { + XeenEngine *vm = Party::_vm; + + if (itemIndex1 >= 0) { + Common::String itemName1 = _character->_items[category1].getName(itemIndex1); + Common::String itemName2 = _character->_items[category2].getName(itemIndex2); + + ErrorDialog::show(vm, Common::String::format(REMOVE_X_TO_EQUIP_Y, + itemName1.c_str(), itemName2.c_str())); + } else { + ErrorDialog::show(vm, Common::String::format(EQUIPPED_ALL_YOU_CAN, + (itemIndex1 == -1) ? RING : MEDAL)); + } +} + +/*------------------------------------------------------------------------*/ + +void WeaponItems::equipItem(int itemIndex) { + XeenItem &item = operator[](itemIndex); + + if (item._id <= 17) { + if (passRestrictions(item._id, false)) { + for (uint idx = 0; idx < size(); ++idx) { + XeenItem &i = operator[](idx); + if (i._frame == 13 || i._frame == 1) { + equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_WEAPON); + return; + } + } + + item._frame = 1; + } + } else if (item._id >= 30 && item._id <= 33) { + if (passRestrictions(item._id, false)) { + for (uint idx = 0; idx < size(); ++idx) { + XeenItem &i = operator[](idx); + if (i._frame == 4) { + equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_WEAPON); + return; + } + } + + item._frame = 4; + } + } else { + if (passRestrictions(item._id, false)) { + for (uint idx = 0; idx < size(); ++idx) { + XeenItem &i = operator[](idx); + if (i._frame == 13 || i._frame == 1) { + equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_WEAPON); + return; + } + } + + for (uint idx = 0; idx < size(); ++idx) { + XeenItem &i = _character->_armor[idx]; + if (i._frame == 2) { + equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_WEAPON); + return; + } + } + + item._frame = 13; + } + } +} + +/*------------------------------------------------------------------------*/ + +void ArmorItems::equipItem(int itemIndex) { error("TODO"); } /*------------------------------------------------------------------------*/ +void AccessoryItems::equipItem(int itemIndex) { + error("TODO"); +} +/*------------------------------------------------------------------------*/ + InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor, InventoryItems &accessories, InventoryItems &misc) { _itemSets[0] = &weapons; @@ -174,8 +263,7 @@ AttributePair::AttributePair() { /*------------------------------------------------------------------------*/ Character::Character(): - _weapons(this, CATEGORY_WEAPON), _armor(this, CATEGORY_ARMOR), - _accessories(this, CATEGORY_ACCESSORY), _misc(this, CATEGORY_MISC), + _weapons(this), _armor(this), _accessories(this), _misc(this), _items(_weapons, _armor, _accessories, _misc) { _sex = MALE; _race = HUMAN; diff --git a/engines/xeen/character.h b/engines/xeen/character.h index b3c9965e9d..c4eae0e706 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -95,24 +95,52 @@ public: }; class InventoryItems : public Common::Array<XeenItem> { -private: +protected: Character *_character; ItemCategory _category; const char *const *_names; + + void equipError(int itemIndex1, ItemCategory category1, int itemIndex2, + ItemCategory category2); public: InventoryItems(Character *character, ItemCategory category); bool passRestrictions(int itemId, bool showError) const; + Common::String getName(int itemIndex); + void discardItem(int itemIndex); - void equipItem(int itemIndex); + virtual void equipItem(int itemIndex) {} void removeItem(int itemIndex); void sort(); }; +class WeaponItems: public InventoryItems { +public: + WeaponItems(Character *character) : InventoryItems(character, CATEGORY_WEAPON) {} + virtual void equipItem(int itemIndex); +}; + +class ArmorItems : public InventoryItems { +public: + ArmorItems(Character *character) : InventoryItems(character, CATEGORY_ARMOR) {} + virtual void equipItem(int itemIndex); +}; + +class AccessoryItems : public InventoryItems { +public: + AccessoryItems(Character *character) : InventoryItems(character, CATEGORY_ACCESSORY) {} + virtual void equipItem(int itemIndex); +}; + +class MiscItems : public InventoryItems { +public: + MiscItems(Character *character) : InventoryItems(character, CATEGORY_MISC) {} +}; + class InventoryItemsGroup { private: InventoryItems *_itemSets[4]; @@ -162,10 +190,10 @@ public: int _currentSpell; int _quickOption; InventoryItemsGroup _items; - InventoryItems _weapons; - InventoryItems _armor; - InventoryItems _accessories; - InventoryItems _misc; + WeaponItems _weapons; + ArmorItems _armor; + AccessoryItems _accessories; + MiscItems _misc; int _lloydSide; AttributePair _fireResistence; AttributePair _coldResistence; diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp index a58e0e9e78..598af1ede7 100644 --- a/engines/xeen/dialogs_error.cpp +++ b/engines/xeen/dialogs_error.cpp @@ -27,29 +27,19 @@ namespace Xeen { -void ErrorScroll::show(XeenEngine *vm, const Common::String &msg, ErrorWaitType waitType) { - ErrorScroll *dlg = new ErrorScroll(vm); +void ErrorDialog::show(XeenEngine *vm, const Common::String &msg, ErrorWaitType waitType) { + ErrorDialog *dlg = new ErrorDialog(vm); dlg->execute(msg, waitType); delete dlg; } -void ErrorScroll::execute(const Common::String &msg, ErrorWaitType waitType) { +void ErrorDialog::execute(const Common::String &msg, ErrorWaitType waitType) { Screen &screen = *_vm->_screen; EventsManager &events = *_vm->_events; Window &w = screen._windows[6]; - Common::String s; - if (waitType == WT_UNFORMATTED) { - // This type isn't technically a waiting type, but it saved on adding - // yet another parameter - waitType = WT_FREEZE_WAIT; - s = msg; - } else { - s = Common::String::format("\x03c\v010\t000%s", msg.c_str()); - } - w.open(); - w.writeString(s); + w.writeString(msg); w.update(); switch (waitType) { @@ -83,4 +73,11 @@ void ErrorScroll::execute(const Common::String &msg, ErrorWaitType waitType) { } } +/*------------------------------------------------------------------------*/ + +void ErrorScroll::show(XeenEngine *vm, const Common::String &msg, ErrorWaitType waitType) { + Common::String s = Common::String::format("\x03c\v010\t000%s", msg.c_str()); + ErrorDialog::show(vm, s, waitType); +} + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_error.h b/engines/xeen/dialogs_error.h index 1a86afce87..644b7e3b0e 100644 --- a/engines/xeen/dialogs_error.h +++ b/engines/xeen/dialogs_error.h @@ -24,19 +24,26 @@ #define XEEN_DIALOGS_ERROR_H #include "xeen/dialogs.h" +#include "xeen/character.h" namespace Xeen { enum ErrorWaitType { WT_FREEZE_WAIT = 0, WT_NONFREEZED_WAIT = 1, - WT_2 = 2, WT_3 = 3, WT_UNFORMATTED = 9 }; + WT_2 = 2, WT_3 = 3 }; -class ErrorScroll: public ButtonContainer { +class ErrorDialog : public ButtonContainer { private: XeenEngine *_vm; - ErrorScroll(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + ErrorDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} void execute(const Common::String &msg, ErrorWaitType waitType); +public: + static void show(XeenEngine *vm, const Common::String &msg, + ErrorWaitType waitType = WT_FREEZE_WAIT); +}; + +class ErrorScroll { public: static void show(XeenEngine *vm, const Common::String &msg, ErrorWaitType waitType = WT_FREEZE_WAIT); diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 1f1c979f7a..c643152f5b 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1125,4 +1125,9 @@ const char *const NO_SPECIAL_ABILITIES = "\v005\x3""c%s\fdhas no special abiliti const char *const CANT_CAST_WHILE_ENGAGED = "\x03c\v007Can't cast %s while engaged!"; +const char *const EQUIPPED_ALL_YOU_CAN = "\x3""c\v007You have equipped all the %ss you can!"; +const char *const REMOVE_X_TO_EQUIP_Y = "\x3""c\v007You must remove %sto equip %s\x8!"; +const char *const RING = "ring"; +const char *const MEDAL = "medal"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 88e01cdb51..c6d2bdeb6d 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -398,6 +398,11 @@ extern const char *const NO_SPECIAL_ABILITIES; extern const char *const CANT_CAST_WHILE_ENGAGED; +extern const char *const EQUIPPED_ALL_YOU_CAN; +extern const char *const REMOVE_X_TO_EQUIP_Y; +extern const char *const RING; +extern const char *const MEDAL; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 3492510db9..5f1df6aef0 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -100,8 +100,8 @@ void Spells::doSpell(int spellId) { if (_vm->_mode == MODE_InCombat) { if (spellId == 15 || spellId == 20 || spellId == 27 || spellId == 41 || spellId == 47 || spellId == 54 || spellId == 57) { - ErrorScroll::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED, - _spellNames[spellId].c_str()), WT_UNFORMATTED); + ErrorDialog::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED, + _spellNames[spellId].c_str())); return; } } -- cgit v1.2.3 From fc04fe6da8b490cceef6ee167775a65fe2e1b607 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 5 Feb 2015 08:00:28 -0500 Subject: XEEN: equipItem methods for armor and accessories --- engines/xeen/character.cpp | 135 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 131 insertions(+), 4 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index 00b7e4333f..b8dd53ddff 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -171,6 +171,9 @@ void InventoryItems::equipError(int itemIndex1, ItemCategory category1, int item /*------------------------------------------------------------------------*/ +/** + * Equip a given weapon + */ void WeaponItems::equipItem(int itemIndex) { XeenItem &item = operator[](itemIndex); @@ -208,10 +211,10 @@ void WeaponItems::equipItem(int itemIndex) { } } - for (uint idx = 0; idx < size(); ++idx) { + for (uint idx = 0; idx < _character->_armor.size(); ++idx) { XeenItem &i = _character->_armor[idx]; if (i._frame == 2) { - equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_WEAPON); + equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_ARMOR); return; } } @@ -223,14 +226,138 @@ void WeaponItems::equipItem(int itemIndex) { /*------------------------------------------------------------------------*/ +/** + * Equip a given piece of armor + */ void ArmorItems::equipItem(int itemIndex) { - error("TODO"); + XeenItem &item = operator[](itemIndex); + + if (item._id <= 7) { + if (passRestrictions(item._id, false)) { + for (uint idx = 0; idx < size(); ++idx) { + XeenItem &i = operator[](idx); + if (i._frame == 9) { + equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR); + return; + } + } + + item._frame = 3; + } + } else if (item._id == 8) { + if (passRestrictions(item._id, false)) { + for (uint idx = 0; idx < size(); ++idx) { + XeenItem &i = operator[](idx); + if (i._frame == 2) { + equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR); + return; + } + } + + for (uint idx = 0; idx < _character->_weapons.size(); ++idx) { + XeenItem &i = _character->_weapons[idx]; + if (i._frame == 13) { + equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_WEAPON); + return; + } + } + + item._frame = 2; + } + } else if (item._id == 9) { + for (uint idx = 0; idx < size(); ++idx) { + XeenItem &i = operator[](idx); + if (i._frame == 5) { + equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR); + return; + } + } + + item._frame = 5; + } else if (item._id == 10) { + for (uint idx = 0; idx < size(); ++idx) { + XeenItem &i = operator[](idx); + if (i._frame == 9) { + equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR); + return; + } + } + + item._frame = 9; + } else if (item._id <= 12) { + for (uint idx = 0; idx < size(); ++idx) { + XeenItem &i = operator[](idx); + if (i._frame == 10) { + equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR); + return; + } + } + + item._frame = 10; + } else { + for (uint idx = 0; idx < size(); ++idx) { + XeenItem &i = operator[](idx); + if (i._frame == 6) { + equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR); + return; + } + } + + item._frame = 6; + } } /*------------------------------------------------------------------------*/ +/** + * Equip a given accessory + */ void AccessoryItems::equipItem(int itemIndex) { - error("TODO"); + XeenItem &item = operator[](itemIndex); + + if (item._id == 1) { + int count = 0; + for (uint idx = 0; idx < size(); ++idx) { + XeenItem &i = operator[](idx); + if (i._frame == 8) + ++count; + } + + if (count <= 1) + item._frame = 8; + else + equipError(-1, CATEGORY_ACCESSORY, itemIndex, CATEGORY_ACCESSORY); + } else if (item._id == 2) { + for (uint idx = 0; idx < size(); ++idx) { + XeenItem &i = operator[](idx); + if (i._frame == 12) { + equipError(itemIndex, CATEGORY_ACCESSORY, idx, CATEGORY_ACCESSORY); + return; + } + } + } else if (item._id <= 7) { + int count = 0; + for (uint idx = 0; idx < size(); ++idx) { + XeenItem &i = operator[](idx); + if (i._frame == 7) + ++count; + } + + if (count <= 1) + item._frame = 7; + else + equipError(-2, CATEGORY_ACCESSORY, itemIndex, CATEGORY_ACCESSORY); + } else { + for (uint idx = 0; idx < size(); ++idx) { + XeenItem &i = operator[](idx); + if (i._frame == 11) { + equipError(itemIndex, CATEGORY_ACCESSORY, idx, CATEGORY_ACCESSORY); + return; + } + } + + item._frame = 11; + } } /*------------------------------------------------------------------------*/ -- cgit v1.2.3 From 85c2dd5f6864540d66e0abfe74ec791bbde41c30 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 5 Feb 2015 20:05:24 -0500 Subject: XEEN: Split up assembleItemName and renamed to getFullDescription --- engines/xeen/character.cpp | 174 ++++++++++++++++++++++++----------------- engines/xeen/character.h | 18 ++++- engines/xeen/dialogs_items.cpp | 19 +++-- engines/xeen/resources.cpp | 4 + engines/xeen/resources.h | 4 + 5 files changed, 138 insertions(+), 81 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index b8dd53ddff..ff85c97855 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -122,9 +122,19 @@ Common::String InventoryItems::getName(int itemIndex) { /** * Discard an item from the inventory */ -void InventoryItems::discardItem(int itemIndex) { - operator[](itemIndex).clear(); - sort(); +bool InventoryItems::discardItem(int itemIndex) { + XeenItem &item = operator[](itemIndex); + XeenEngine *vm = Party::_vm; + + if (item._bonusFlags & ITEMFLAG_CURSED) { + ErrorScroll::show(vm, CANNOT_DISCARD_CURSED_ITEM); + return false; + } else { + Common::String itemDesc = getFullDescription(itemIndex, 4); + + error("TODO: discardItem - %s", itemDesc.c_str()); + } + error("TODO"); } /** @@ -149,8 +159,21 @@ void InventoryItems::sort() { } } +/** + * Un-equips the given item + */ void InventoryItems::removeItem(int itemIndex) { - error("TODO"); + XeenItem &item = operator[](itemIndex); + XeenEngine *vm = Party::_vm; + + if (item._bonusFlags & ITEMFLAG_CURSED) + ErrorScroll::show(vm, CANNOT_REMOVE_CURSED_ITEM); + else + item._frame = 0; +} + +XeenEngine *InventoryItems::vm() { + return Party::_vm; } void InventoryItems::equipError(int itemIndex1, ItemCategory category1, int itemIndex2, @@ -224,6 +247,25 @@ void WeaponItems::equipItem(int itemIndex) { } } +/** + * Assembles a full lines description for a specified item for use in + * the Items dialog + */ +Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) { + XeenItem &i = operator[](itemIndex); + Spells &spells = *vm()->_spells; + + return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum, + !i._bonusFlags ? spells._maeNames[i._material] : "", + (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", + (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + WEAPON_NAMES[i._id], + !i._bonusFlags ? "" : BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK], + (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || + !i._bonusFlags ? "\b " : "" + ); +} + /*------------------------------------------------------------------------*/ /** @@ -307,6 +349,24 @@ void ArmorItems::equipItem(int itemIndex) { } } +/** + * Assembles a full lines description for a specified item for use in + * the Items dialog + */ +Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) { + XeenItem &i = operator[](itemIndex); + Spells &spells = *vm()->_spells; + + return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, + !i._bonusFlags ? "" : spells._maeNames[i._material], + (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", + (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + ARMOR_NAMES[i._id], + (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || + !i._bonusFlags ? "\b " : "" + ); +} + /*------------------------------------------------------------------------*/ /** @@ -359,6 +419,46 @@ void AccessoryItems::equipItem(int itemIndex) { item._frame = 11; } } + +/** + * Assembles a full lines description for a specified item for use in + * the Items dialog + */ +Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum) { + Spells &spells = *vm()->_spells; + XeenItem &i = operator[](itemIndex); + + return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, + !i._bonusFlags ? "" : spells._maeNames[i._material], + (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", + (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + ARMOR_NAMES[i._id], + (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || + !i._bonusFlags ? "\b " : "" + ); +} + +/*------------------------------------------------------------------------*/ + +/** + * Assembles a full lines description for a specified item for use in + * the Items dialog + */ +Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) { + XeenItem &i = operator[](itemIndex); + Spells &spells = *vm()->_spells; + + return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, + !i._bonusFlags ? "" : spells._maeNames[i._material], + (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", + (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + ARMOR_NAMES[i._id], + (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || + !i._id ? "\b " : "" + ); +} + + /*------------------------------------------------------------------------*/ InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor, @@ -1203,70 +1303,4 @@ int Character::getNumAwards() const { return total; } -/** - * Assembles a full lines description for a specified item for use in - * the Items dialog - */ -Common::String Character::assembleItemName(int itemIndex, int displayNum, - ItemCategory category) { - Spells &spells = *Party::_vm->_spells; - - switch (category) { - case CATEGORY_WEAPON: { - // Weapons - XeenItem &i = _weapons[itemIndex]; - return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum, - !i._bonusFlags ? spells._maeNames[i._material] : "", - (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", - (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", - WEAPON_NAMES[i._id], - !i._bonusFlags ? "" : BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK], - (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || - !i._bonusFlags ? "\b " : "" - ); - } - - case CATEGORY_ARMOR: { - // Armor - XeenItem &i = _armor[itemIndex]; - return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, - !i._bonusFlags ? "" : spells._maeNames[i._material], - (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", - (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", - ARMOR_NAMES[i._id], - (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || - !i._bonusFlags ? "\b " : "" - ); - } - - case CATEGORY_ACCESSORY: { - // Accessories - XeenItem &i = _accessories[itemIndex]; - return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, - !i._bonusFlags ? "" : spells._maeNames[i._material], - (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", - (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", - ARMOR_NAMES[i._id], - (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || - !i._bonusFlags ? "\b " : "" - ); - } - - case CATEGORY_MISC: { - // Misc - XeenItem &i = _misc[itemIndex]; - return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, - !i._bonusFlags ? "" : spells._maeNames[i._material], - (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", - (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", - ARMOR_NAMES[i._id], - (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || - !i._id ? "\b " : "" - ); - } - default: - return ""; - } -} - } // End of namespace Xeen diff --git a/engines/xeen/character.h b/engines/xeen/character.h index c4eae0e706..6514caeaa1 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -100,6 +100,7 @@ protected: ItemCategory _category; const char *const *_names; + XeenEngine *vm(); void equipError(int itemIndex1, ItemCategory category1, int itemIndex2, ItemCategory category2); public: @@ -109,7 +110,9 @@ public: Common::String getName(int itemIndex); - void discardItem(int itemIndex); + virtual Common::String getFullDescription(int itemIndex, int displayNum) = 0; + + bool discardItem(int itemIndex); virtual void equipItem(int itemIndex) {} @@ -121,24 +124,35 @@ public: class WeaponItems: public InventoryItems { public: WeaponItems(Character *character) : InventoryItems(character, CATEGORY_WEAPON) {} + virtual void equipItem(int itemIndex); + + virtual Common::String getFullDescription(int itemIndex, int displayNum); }; class ArmorItems : public InventoryItems { public: ArmorItems(Character *character) : InventoryItems(character, CATEGORY_ARMOR) {} + virtual void equipItem(int itemIndex); + + virtual Common::String getFullDescription(int itemIndex, int displayNum); }; class AccessoryItems : public InventoryItems { public: AccessoryItems(Character *character) : InventoryItems(character, CATEGORY_ACCESSORY) {} + virtual void equipItem(int itemIndex); + + virtual Common::String getFullDescription(int itemIndex, int displayNum); }; class MiscItems : public InventoryItems { public: MiscItems(Character *character) : InventoryItems(character, CATEGORY_MISC) {} + + virtual Common::String getFullDescription(int itemIndex, int displayNum); }; class InventoryItemsGroup { @@ -257,8 +271,6 @@ public: int getNumSkills() const; int getNumAwards() const; - - Common::String assembleItemName(int itemIndex, int displayNum, ItemCategory category); }; } // End of namespace Xeen diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index c28085c15e..beaf5652d7 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -141,11 +141,11 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { || mode == ITEMMODE_6 || mode == ITEMMODE_4) { lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, arr[idx], idx + 1, - c->assembleItemName(idx, arr[idx], category))); + c->_items[category].getFullDescription(idx, arr[idx]))); } else { lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2, arr[idx], idx + 1, - c->assembleItemName(idx, arr[idx], category), + c->_items[category].getFullDescription(idx, arr[idx]), calcItemCost(c, idx, mode, mode == ITEMMODE_TO_GOLD ? 1 : startingChar->_skills[MERCHANT], category) @@ -186,7 +186,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2, arr[idx], idx + 1, - c->assembleItemName(idx, arr[idx], category), + c->_items[category].getFullDescription(idx, arr[idx]), calcItemCost(c, idx, tempMode, skill, category) )); } @@ -631,8 +631,8 @@ bool ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, It ErrorScroll::show(_vm, USE_ITEM_IN_COMBAT); } else if (i._id && (i._bonusFlags & ITEMFLAG_BONUS_MASK) && !(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED))) { - int bonus = (i._bonusFlags & ITEMFLAG_BONUS_MASK) - 1; - i._bonusFlags = bonus; + int charges = (i._bonusFlags & ITEMFLAG_BONUS_MASK) - 1; + i._bonusFlags = charges; _oldCharacter = &c; screen._windows[30].close(); @@ -640,16 +640,19 @@ bool ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, It screen._windows[24].close(); spells.doSpell(i._id); - if (!bonus) { - c._items[category].discardItem(itemIndex); + if (!charges) { + // Ran out of charges, so make item disappear + c._items[category][itemIndex].clear(); + c._items[category].sort(); } } else { ErrorScroll::show(_vm, Common::String::format(NO_SPECIAL_ABILITIES, - c.assembleItemName(itemIndex, 15, category).c_str() + c._items[category].getFullDescription(itemIndex, 15).c_str() )); } } } + break; case 3: // TODO: Remaining switches default: diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index c643152f5b..b38868f7a4 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1130,4 +1130,8 @@ const char *const REMOVE_X_TO_EQUIP_Y = "\x3""c\v007You must remove %sto equip % const char *const RING = "ring"; const char *const MEDAL = "medal"; +const char *const CANNOT_REMOVE_CURSED_ITEM = "\x3""You cannot remove a cursed item!"; + +const char *const CANNOT_DISCARD_CURSED_ITEM = "\3x""cYou cannot discard a cursed item!"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index c6d2bdeb6d..e1f276b91c 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -403,6 +403,10 @@ extern const char *const REMOVE_X_TO_EQUIP_Y; extern const char *const RING; extern const char *const MEDAL; +extern const char *const CANNOT_REMOVE_CURSED_ITEM; + +extern const char *const CANNOT_DISCARD_CURSED_ITEM; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From 6595abcf144850cc23208db71ce0098d9921112e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 5 Feb 2015 20:17:16 -0500 Subject: XEEN: Moved _maeNames to a new Resources class --- engines/xeen/character.cpp | 17 ++++++++--------- engines/xeen/resources.cpp | 10 ++++++++++ engines/xeen/resources.h | 11 +++++++++++ engines/xeen/spells.cpp | 5 ----- engines/xeen/spells.h | 1 - engines/xeen/xeen.cpp | 3 +++ engines/xeen/xeen.h | 2 ++ 7 files changed, 34 insertions(+), 15 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index ff85c97855..20cbfbd0fc 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -253,10 +253,10 @@ void WeaponItems::equipItem(int itemIndex) { */ Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) { XeenItem &i = operator[](itemIndex); - Spells &spells = *vm()->_spells; + Resources &res = *vm()->_resources; return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum, - !i._bonusFlags ? spells._maeNames[i._material] : "", + !i._bonusFlags ? res._maeNames[i._material] : "", (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", WEAPON_NAMES[i._id], @@ -355,10 +355,10 @@ void ArmorItems::equipItem(int itemIndex) { */ Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) { XeenItem &i = operator[](itemIndex); - Spells &spells = *vm()->_spells; + Resources &res = *vm()->_resources; return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, - !i._bonusFlags ? "" : spells._maeNames[i._material], + !i._bonusFlags ? "" : res._maeNames[i._material], (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", ARMOR_NAMES[i._id], @@ -425,11 +425,11 @@ void AccessoryItems::equipItem(int itemIndex) { * the Items dialog */ Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum) { - Spells &spells = *vm()->_spells; XeenItem &i = operator[](itemIndex); + Resources &res = *vm()->_resources; return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, - !i._bonusFlags ? "" : spells._maeNames[i._material], + !i._bonusFlags ? "" : res._maeNames[i._material], (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", ARMOR_NAMES[i._id], @@ -446,10 +446,10 @@ Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum) */ Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) { XeenItem &i = operator[](itemIndex); - Spells &spells = *vm()->_spells; + Resources &res = *vm()->_resources; return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, - !i._bonusFlags ? "" : spells._maeNames[i._material], + !i._bonusFlags ? "" : res._maeNames[i._material], (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", ARMOR_NAMES[i._id], @@ -458,7 +458,6 @@ Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) { ); } - /*------------------------------------------------------------------------*/ InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor, diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index b38868f7a4..5cd09cf422 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -22,9 +22,19 @@ #include "common/scummsys.h" #include "xeen/resources.h" +#include "xeen/files.h" namespace Xeen { +Resources::Resources() { + File f("mae.xen"); + while (f.pos() < f.size()) + _maeNames.push_back(f.readString()); + f.close(); +} + +/*------------------------------------------------------------------------*/ + const char *const CREDITS = "\013""012\010""000\003""c\014""35Designed and Directed By:\n" "\014""17Jon Van Caneghem\003""l\n" diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index e1f276b91c..8be195f34e 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -24,10 +24,21 @@ #define XEEN_RESOURCES_H #include "common/scummsys.h" +#include "common/str-array.h" #include "gui/debugger.h" namespace Xeen { +class Resources { +public: + // Magic and equipment names + Common::StringArray _maeNames; +public: + Resources(); +}; + +#define Res (*_vm->_resources) + extern const char *const CREDITS; extern const char *const OPTIONS_TITLE; diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 5f1df6aef0..50e77668cd 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -38,11 +38,6 @@ void Spells::load() { while (f1.pos() < f1.size()) _spellNames.push_back(f1.readString()); f1.close(); - - File f2("mae.xen"); - while (f2.pos() < f2.size()) - _maeNames.push_back(f2.readString()); - f2.close(); } int Spells::calcSpellCost(int spellId, int expenseFactor) const { diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h index 241d35dca7..c2f9737c80 100644 --- a/engines/xeen/spells.h +++ b/engines/xeen/spells.h @@ -121,7 +121,6 @@ private: void divineIntervention(); public: Common::StringArray _spellNames; - Common::StringArray _maeNames; int _lastCaster; public: Spells(XeenEngine *vm); diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index d7a85fbbf8..d34e8edb21 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -43,6 +43,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _interface = nullptr; _map = nullptr; _party = nullptr; + _resources = nullptr; _saves = nullptr; _screen = nullptr; _scripts = nullptr; @@ -72,6 +73,7 @@ XeenEngine::~XeenEngine() { delete _spells; delete _town; delete _eventData; + delete _resources; delete _files; } @@ -84,6 +86,7 @@ void XeenEngine::initialize() { // Create sub-objects of the engine _files = new FileManager(this); + _resources = new Resources(); _combat = new Combat(this); _debugger = new Debugger(this); _events = new EventsManager(this); diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 7f1a2cd0f0..af2044b212 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -39,6 +39,7 @@ #include "xeen/interface.h" #include "xeen/map.h" #include "xeen/party.h" +#include "xeen/resources.h" #include "xeen/saves.h" #include "xeen/screen.h" #include "xeen/scripts.h" @@ -139,6 +140,7 @@ public: Interface *_interface; Map *_map; Party *_party; + Resources *_resources; SavesManager *_saves; Screen *_screen; Scripts *_scripts; -- cgit v1.2.3 From b39f4179ce53e9e98c4e3d80cc0f075dabd8d8f6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 5 Feb 2015 20:47:15 -0500 Subject: XEEN: Merged confirmation and yes/no dialogs into single source file --- engines/xeen/character.cpp | 13 +++- engines/xeen/dialogs_confirm.cpp | 85 --------------------- engines/xeen/dialogs_confirm.h | 43 ----------- engines/xeen/dialogs_query.cpp | 159 +++++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_query.h | 54 +++++++++++++ engines/xeen/dialogs_spells.cpp | 4 +- engines/xeen/dialogs_yesno.cpp | 96 ----------------------- engines/xeen/dialogs_yesno.h | 43 ----------- engines/xeen/module.mk | 3 +- engines/xeen/resources.cpp | 2 + engines/xeen/resources.h | 2 + engines/xeen/scripts.cpp | 2 +- engines/xeen/town.cpp | 2 +- 13 files changed, 232 insertions(+), 276 deletions(-) delete mode 100644 engines/xeen/dialogs_confirm.cpp delete mode 100644 engines/xeen/dialogs_confirm.h create mode 100644 engines/xeen/dialogs_query.cpp create mode 100644 engines/xeen/dialogs_query.h delete mode 100644 engines/xeen/dialogs_yesno.cpp delete mode 100644 engines/xeen/dialogs_yesno.h (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index 20cbfbd0fc..8fd7a35c5f 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -21,6 +21,7 @@ */ #include "xeen/character.h" +#include "xeen/dialogs_query.h" #include "xeen/dialogs_error.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -128,13 +129,19 @@ bool InventoryItems::discardItem(int itemIndex) { if (item._bonusFlags & ITEMFLAG_CURSED) { ErrorScroll::show(vm, CANNOT_DISCARD_CURSED_ITEM); - return false; } else { Common::String itemDesc = getFullDescription(itemIndex, 4); + Common::String msg = Common::String::format(PERMANENTLY_DISCARD, itemDesc.c_str()); + + if (Confirm::show(vm, msg)) { + operator[](itemIndex).clear(); + sort(); - error("TODO: discardItem - %s", itemDesc.c_str()); + return true; + } } - error("TODO"); + + return true; } /** diff --git a/engines/xeen/dialogs_confirm.cpp b/engines/xeen/dialogs_confirm.cpp deleted file mode 100644 index 13a41e76ca..0000000000 --- a/engines/xeen/dialogs_confirm.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* 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 "xeen/dialogs_confirm.h" -#include "xeen/xeen.h" - -namespace Xeen { - -bool ConfirmDialog::show(XeenEngine *vm, const Common::String &msg, int v2) { - ConfirmDialog *dlg = new ConfirmDialog(vm); - bool result = dlg->execute(msg, v2); - delete dlg; - - return result; -} - -bool ConfirmDialog::execute(const Common::String &msg, int v2) { - Screen &screen = *_vm->_screen; - EventsManager &events = *_vm->_events; - SpriteResource confirmSprites; - confirmSprites.load("confirm.icn"); - - addButton(Common::Rect(129, 112, 153, 132), Common::KEYCODE_y, &confirmSprites); - addButton(Common::Rect(185, 112, 209, 132), Common::KEYCODE_n, &confirmSprites); - - Window &w = screen._windows[v2 ? 21 : 22]; - w.open(); - - if (v2) { - confirmSprites.draw(screen._windows[21], 0, Common::Point(129, 112)); - confirmSprites.draw(screen._windows[21], 2, Common::Point(185, 112)); - - _buttons[0]._bounds.moveTo(129, 112); - _buttons[1]._bounds.moveTo(185, 112); - } else if (v2 & 0x80) { - clearButtons(); - } else { - confirmSprites.draw(screen._windows[22], 0, Common::Point(120, 133)); - confirmSprites.draw(screen._windows[22], 2, Common::Point(176, 133)); - - _buttons[0]._bounds.moveTo(120, 133); - _buttons[1]._bounds.moveTo(176, 133); - } - - w.writeString(msg); - w.update(); - - bool result = false; - while (!_vm->shouldQuit()) { - while (!events.isKeyMousePressed()) - events.pollEventsAndWait(); - - if ((v2 & 0x80) || _buttonValue == Common::KEYCODE_ESCAPE || - _buttonValue == Common::KEYCODE_y) - break; - else if (_buttonValue == Common::KEYCODE_y) { - result = true; - break; - } - } - - w.close(); - return result; -} - -} // End of namespace Xeen diff --git a/engines/xeen/dialogs_confirm.h b/engines/xeen/dialogs_confirm.h deleted file mode 100644 index 825be5e764..0000000000 --- a/engines/xeen/dialogs_confirm.h +++ /dev/null @@ -1,43 +0,0 @@ -/* 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 XEEN_DIALOGS_CONFIRM_H -#define XEEN_DIALOGS_CONFIRM_H - -#include "xeen/dialogs.h" - -namespace Xeen { - -class ConfirmDialog : public ButtonContainer { -private: - XeenEngine *_vm; - - ConfirmDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} - - bool execute(const Common::String &msg, int v2); -public: - static bool show(XeenEngine *vm, const Common::String &msg, int v2); -}; - -} // End of namespace Xeen - -#endif /* XEEN_DIALOGS_CONFIRM_H */ diff --git a/engines/xeen/dialogs_query.cpp b/engines/xeen/dialogs_query.cpp new file mode 100644 index 0000000000..f226521a94 --- /dev/null +++ b/engines/xeen/dialogs_query.cpp @@ -0,0 +1,159 @@ +/* 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 "xeen/dialogs_query.h" +#include "xeen/xeen.h" + +namespace Xeen { + +bool Confirm::show(XeenEngine *vm, const Common::String &msg, int mode) { + Confirm *dlg = new Confirm(vm); + bool result = dlg->execute(msg, mode); + delete dlg; + + return result; +} + +bool Confirm::execute(const Common::String &msg, int mode) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + SpriteResource confirmSprites; + bool result = false; + + confirmSprites.load("confirm.icn"); + addButton(Common::Rect(129, 112, 153, 122), Common::KEYCODE_y, &confirmSprites); + addButton(Common::Rect(185, 112, 209, 122), Common::KEYCODE_n, &confirmSprites); + + Window &w = screen._windows[mode ? 22 : 21]; + w.open(); + + if (!mode) { + confirmSprites.draw(w, 0, Common::Point(129, 112)); + confirmSprites.draw(w, 2, Common::Point(185, 112)); + _buttons[0]._bounds.moveTo(129, 112); + _buttons[1]._bounds.moveTo(185, 112); + } else { + if (mode & 0x80) { + clearButtons(); + } else { + confirmSprites.draw(w, 0, Common::Point(120, 133)); + confirmSprites.draw(w, 2, Common::Point(176, 133)); + _buttons[0]._bounds.moveTo(120, 133); + _buttons[1]._bounds.moveTo(176, 133); + } + } + + w.writeString(msg); + w.update(); + + events.clearEvents(); + while (!_vm->shouldQuit()) { + while (!_vm->shouldQuit() && !_buttonValue) { + events.pollEvents(); + checkEvents(_vm); + } + + if ((mode & 0x80) || _buttonValue == Common::KEYCODE_ESCAPE + || _buttonValue == Common::KEYCODE_n) + break; + + if (_buttonValue == Common::KEYCODE_y) { + result = true; + break; + } + } + + w.close(); + return result; +} + +/*------------------------------------------------------------------------*/ + +bool YesNo::show(XeenEngine *vm, bool type, bool townFlag) { + YesNo *dlg = new YesNo(vm); + bool result = dlg->execute(type, townFlag); + delete dlg; + + return result; +} + +bool YesNo::execute(bool type, bool townFlag) { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Town &town = *_vm->_town; + SpriteResource confirmSprites; + int numFrames; + bool result = false; + + Mode oldMode = _vm->_mode; + _vm->_mode = oldMode == MODE_7 ? MODE_8 : MODE_7; + + if (!type) { + confirmSprites.load("confirm.icn"); + intf._globalSprites.draw(screen, 7, Common::Point(232, 74)); + confirmSprites.draw(screen, 0, Common::Point(235, 75)); + confirmSprites.draw(screen, 2, Common::Point(260, 75)); + screen._windows[34].update(); + + addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_y, &confirmSprites); + addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_n, &confirmSprites); + + intf._face1State = map._headData[party._mazePosition.y][party._mazePosition.x]._left; + intf._face2State = map._headData[party._mazePosition.y][party._mazePosition.x]._right; + } + + while (!_vm->shouldQuit()) { + events.updateGameCounter(); + + if (town.isActive()) { + town.drawTownAnim(townFlag); + numFrames = 3; + } else { + intf.draw3d(true); + numFrames = 1; + } + + events.wait(3, true); + checkEvents(_vm); + if (!_buttonValue) + continue; + + if (type || _buttonValue == Common::KEYCODE_y) { + result = true; + break; + } else if (_buttonValue == Common::KEYCODE_n || _buttonValue == Common::KEYCODE_ESCAPE) + break; + } + + intf._face1State = intf._face2State = 2; + _vm->_mode = oldMode; + + if (!type) + intf.mainIconsPrint(); + + return result; +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_query.h b/engines/xeen/dialogs_query.h new file mode 100644 index 0000000000..96ae488b97 --- /dev/null +++ b/engines/xeen/dialogs_query.h @@ -0,0 +1,54 @@ +/* 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 XEEN_DIALOGS_QUERY_H +#define XEEN_DIALOGS_QUERY_H + +#include "xeen/dialogs.h" + +namespace Xeen { + +class Confirm : public ButtonContainer { +private: + XeenEngine *_vm; + + Confirm(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + bool execute(const Common::String &msg, int mode); +public: + static bool show(XeenEngine *vm, const Common::String &msg, int mode = 0); +}; + +class YesNo : public ButtonContainer { +private: + XeenEngine *_vm; + + YesNo(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + bool execute(bool type, bool townFlag); +public: + static bool show(XeenEngine *vm, bool type, bool townFlag = false); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_QUERY_H */ diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 714e881128..4f86707554 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -21,7 +21,7 @@ */ #include "xeen/dialogs_spells.h" -#include "xeen/dialogs_confirm.h" +#include "xeen/dialogs_query.h" #include "xeen/resources.h" #include "xeen/spells.h" #include "xeen/sprites.h" @@ -216,7 +216,7 @@ Character *SpellsScroll::execute(Character *c, int v2) { Common::String::format(SPELLS_PRESS_A_KEY, msg.c_str()) : Common::String::format(SPELLS_PURCHASE, msg.c_str(), spellCost); - if (ConfirmDialog::show(_vm, msg, v2Copy + 1)) { + if (Confirm::show(_vm, msg, v2Copy + 1)) { if (party.subtract(0, spellCost, 0, WT_FREEZE_WAIT)) { ++c->_spells[spellIndex]; sound.playSample(nullptr, 0); diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp deleted file mode 100644 index 17ca9a0c3e..0000000000 --- a/engines/xeen/dialogs_yesno.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* 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 "xeen/dialogs_yesno.h" -#include "xeen/xeen.h" - -namespace Xeen { - -bool YesNo::show(XeenEngine *vm, bool type, bool townFlag) { - YesNo *dlg = new YesNo(vm); - bool result = dlg->execute(type, townFlag); - delete dlg; - - return result; -} - -bool YesNo::execute(bool type, bool townFlag) { - Screen &screen = *_vm->_screen; - EventsManager &events = *_vm->_events; - Interface &intf = *_vm->_interface; - Map &map = *_vm->_map; - Party &party = *_vm->_party; - Town &town = *_vm->_town; - SpriteResource confirmSprites; - int numFrames; - bool result = false; - - Mode oldMode = _vm->_mode; - _vm->_mode = oldMode == MODE_7 ? MODE_8 : MODE_7; - - if (!type) { - confirmSprites.load("confirm.icn"); - intf._globalSprites.draw(screen, 7, Common::Point(232, 74)); - confirmSprites.draw(screen, 0, Common::Point(235, 75)); - confirmSprites.draw(screen, 2, Common::Point(260, 75)); - screen._windows[34].update(); - - addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_y, &confirmSprites); - addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_n, &confirmSprites); - - intf._face1State = map._headData[party._mazePosition.y][party._mazePosition.x]._left; - intf._face2State = map._headData[party._mazePosition.y][party._mazePosition.x]._right; - } - - while (!_vm->shouldQuit()) { - events.updateGameCounter(); - - if (town.isActive()) { - town.drawTownAnim(townFlag); - numFrames = 3; - } else { - intf.draw3d(true); - numFrames = 1; - } - - events.wait(3, true); - checkEvents(_vm); - if (!_buttonValue) - continue; - - if (type || _buttonValue == Common::KEYCODE_y) { - result = true; - break; - } else if (_buttonValue == Common::KEYCODE_n || _buttonValue == Common::KEYCODE_ESCAPE) - break; - } - - intf._face1State = intf._face2State = 2; - _vm->_mode = oldMode; - - if (!type) - intf.mainIconsPrint(); - - return result; -} - -} // End of namespace Xeen diff --git a/engines/xeen/dialogs_yesno.h b/engines/xeen/dialogs_yesno.h deleted file mode 100644 index 96c3592d9d..0000000000 --- a/engines/xeen/dialogs_yesno.h +++ /dev/null @@ -1,43 +0,0 @@ -/* 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 XEEN_DIALOGS_YESNO_H -#define XEEN_DIALOGS_YESNO_H - -#include "xeen/dialogs.h" - -namespace Xeen { - -class YesNo : public ButtonContainer { -private: - XeenEngine *_vm; - - YesNo(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} - - bool execute(bool type, bool townFlag); -public: - static bool show(XeenEngine *vm, bool type, bool townFlag = false); -}; - -} // End of namespace Xeen - -#endif /* XEEN_DIALOGS_YESNO_H */ diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 25568523cd..6a36f91bf8 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -12,17 +12,16 @@ MODULE_OBJS := \ automap.o \ dialogs_automap.o \ dialogs_char_info.o \ - dialogs_confirm.o \ dialogs_error.o \ dialogs_exchange.o \ dialogs_options.o \ dialogs_info.o \ dialogs_input.o \ dialogs_items.o \ + dialogs_query.o \ dialogs_quick_ref.o \ dialogs_spells.o \ dialogs_whowill.o \ - dialogs_yesno.o \ events.o \ files.o \ font.o \ diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 5cd09cf422..0f6588af9a 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1144,4 +1144,6 @@ const char *const CANNOT_REMOVE_CURSED_ITEM = "\x3""You cannot remove a cursed i const char *const CANNOT_DISCARD_CURSED_ITEM = "\3x""cYou cannot discard a cursed item!"; +const char *const PERMANENTLY_DISCARD = "\v000\t000\x03lPermanently discard %s\fd?"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 8be195f34e..87b9468064 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -418,6 +418,8 @@ extern const char *const CANNOT_REMOVE_CURSED_ITEM; extern const char *const CANNOT_DISCARD_CURSED_ITEM; +extern const char *const PERMANENTLY_DISCARD; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 12fe2f1257..4859e93405 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -23,7 +23,7 @@ #include "xeen/scripts.h" #include "xeen/dialogs_input.h" #include "xeen/dialogs_whowill.h" -#include "xeen/dialogs_yesno.h" +#include "xeen/dialogs_query.h" #include "xeen/party.h" #include "xeen/resources.h" #include "xeen/xeen.h" diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 3df26859d4..3a07d2a9e0 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -23,7 +23,7 @@ #include "xeen/town.h" #include "xeen/dialogs_input.h" #include "xeen/dialogs_items.h" -#include "xeen/dialogs_yesno.h" +#include "xeen/dialogs_query.h" #include "xeen/dialogs_spells.h" #include "xeen/resources.h" #include "xeen/xeen.h" -- cgit v1.2.3 From d40c62532abfeb0d7fdbc005a16698ce19afe43b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 6 Feb 2015 20:57:01 -0500 Subject: XEEN: Implemented makeItem --- engines/xeen/character.cpp | 313 +++++++++++++++++++++++++++++++++++++++++ engines/xeen/character.h | 15 +- engines/xeen/dialogs_items.cpp | 144 ++++++++++++++++--- engines/xeen/dialogs_items.h | 4 +- engines/xeen/resources.cpp | 49 +++++++ engines/xeen/resources.h | 24 ++++ engines/xeen/scripts.h | 2 +- 7 files changed, 526 insertions(+), 25 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index 8fd7a35c5f..3489783983 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -73,6 +73,11 @@ InventoryItems::InventoryItems(Character *character, ItemCategory category): _names = NAMES[category]; } +void InventoryItems::clear() { + for (uint idx = 0; idx < size(); ++idx) + operator[](idx).clear(); +} + /** * Return whether a given item passes class-based usage restrictions */ @@ -199,6 +204,12 @@ void InventoryItems::equipError(int itemIndex1, ItemCategory category1, int item } } +void InventoryItems::enchantItem(int itemIndex, int amount) { + XeenEngine *vm = Party::_vm; + vm->_sound->playFX(21); + ErrorScroll::show(vm, Common::String::format(NOT_ENCHANTABLE, SPELL_FAILED)); +} + /*------------------------------------------------------------------------*/ /** @@ -273,6 +284,23 @@ Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) { ); } +void WeaponItems::enchantItem(int itemIndex, int amount) { + SoundManager &sound = *vm()->_sound; + XeenItem &item = operator[](itemIndex); + Character tempCharacter; + + if (item._material == 0 && item._bonusFlags == 0 && item._id != 34) { + tempCharacter.makeItem(amount, 0, 1); + XeenItem &tempItem = tempCharacter._weapons[0]; + + item._material = tempItem._material; + item._bonusFlags = tempItem._bonusFlags; + sound.playFX(19); + } else { + InventoryItems::enchantItem(itemIndex, amount); + } +} + /*------------------------------------------------------------------------*/ /** @@ -374,6 +402,23 @@ Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) { ); } +void ArmorItems::enchantItem(int itemIndex, int amount) { + SoundManager &sound = *vm()->_sound; + XeenItem &item = operator[](itemIndex); + Character tempCharacter; + + if (item._material == 0 && item._bonusFlags == 0) { + tempCharacter.makeItem(amount, 0, 2); + XeenItem &tempItem = tempCharacter._armor[0]; + + item._material = tempItem._material; + item._bonusFlags = tempItem._bonusFlags; + sound.playFX(19); + } else { + InventoryItems::enchantItem(itemIndex, amount); + } +} + /*------------------------------------------------------------------------*/ /** @@ -498,6 +543,10 @@ AttributePair::AttributePair() { Character::Character(): _weapons(this), _armor(this), _accessories(this), _misc(this), _items(_weapons, _armor, _accessories, _misc) { + clear(); +} + +void Character::clear() { _sex = MALE; _race = HUMAN; _xeenSide = 0; @@ -522,6 +571,24 @@ Character::Character(): _experience = 0; _currentAdventuringSpell = 0; _currentCombatSpell = 0; + + _might._permanent = _might._temporary = 0; + _intellect._permanent = _intellect._temporary = 0; + _personality._permanent = _personality._temporary = 0; + _endurance._permanent = _endurance._temporary = 0; + _speed._permanent = _speed._temporary = 0; + _accuracy._permanent = _accuracy._temporary = 0; + _luck._permanent = _luck._temporary = 0; + _fireResistence._permanent = _fireResistence._temporary = 0; + _coldResistence._permanent = _coldResistence._temporary = 0; + _electricityResistence._permanent = _electricityResistence._temporary = 0; + _poisonResistence._permanent = _poisonResistence._temporary = 0; + _energyResistence._permanent = _energyResistence._temporary = 0; + _magicResistence._permanent = _magicResistence._temporary = 0; + _weapons.clear(); + _armor.clear(); + _accessories.clear(); + _misc.clear(); } void Character::synchronize(Common::Serializer &s) { @@ -1309,4 +1376,250 @@ int Character::getNumAwards() const { return total; } +int Character::makeItem(int p1, int itemIndex, int p3) { + XeenEngine *vm = Party::_vm; + Scripts &scripts = *vm->_scripts; + + if (!p1) + return 0; + + int itemId = 0; + int v4 = vm->getRandomNumber(100); + int v6 = vm->getRandomNumber(p1 < 6 ? 100 : 80); + ItemCategory category; + int v16 = 0, v14 = 0, miscBonus = 0, miscId = 0, v8 = 0, v12 = 0; + + // Randomly pick a category and item Id + if (p3 == 12) { + if (scripts._itemType < 35) { + category = CATEGORY_WEAPON; + itemId = scripts._itemType; + } else if (scripts._itemType < 49) { + category = CATEGORY_ARMOR; + itemId = scripts._itemType - 35; + } else if (scripts._itemType < 60) { + category = CATEGORY_ACCESSORY; + itemId = scripts._itemType - 49; + } else { + category = CATEGORY_MISC; + itemId = scripts._itemType - 60; + } + } else { + switch (p3) { + case 1: + v4 = 35; + break; + case 2: + v4 = 60; + break; + case 3: + v4 = 100; + break; + default: + break; + } + + if (p1 == 1) { + if (v4 <= 40) { + category = CATEGORY_WEAPON; + if (v6 <= 30) { + itemId = vm->getRandomNumber(1, 6); + } else if (v6 <= 60) { + itemId = vm->getRandomNumber(7, 17); + } else if (v6 <= 85) { + itemId = vm->getRandomNumber(18, 29); + } else { + itemId = vm->getRandomNumber(30, 33); + } + } else if (v4 <= 85) { + category = CATEGORY_ARMOR; + itemId = vm->getRandomNumber(1, 7); + } else { + category = CATEGORY_MISC; + itemId = vm->getRandomNumber(1, 9); + } + } else if (v4 <= 35) { + category = CATEGORY_WEAPON; + if (v6 <= 30) { + itemId = vm->getRandomNumber(1, 6); + } else if (v6 <= 60) { + itemId = vm->getRandomNumber(7, 17); + } else if (v6 <= 85) { + itemId = vm->getRandomNumber(18, 29); + } else { + itemId = vm->getRandomNumber(30, 33); + } + } else if (v4 <= 60) { + category = CATEGORY_ARMOR; + itemId = (v6 > 70) ? 8 : vm->getRandomNumber(1, 7); + } else if (v6 <= 10) { + category = CATEGORY_ARMOR; + itemId = 9; + } else if (v6 <= 20) { + category = CATEGORY_ARMOR; + itemId = 13; + } else if (v6 <= 35) { + category = CATEGORY_ACCESSORY; + itemId = 1; + } else if (v6 <= 45) { + category = CATEGORY_ARMOR; + itemId = 10; + } else if (v6 <= 55) { + category = CATEGORY_ARMOR; + itemId = vm->getRandomNumber(11, 12); + } else if (v6 <= 65) { + category = CATEGORY_ACCESSORY; + itemId = 2; + } else if (v6 <= 75) { + category = CATEGORY_ACCESSORY; + itemId = vm->getRandomNumber(3, 7); + } else if (v6 <= 80) { + category = CATEGORY_ACCESSORY; + itemId = vm->getRandomNumber(8, 10); + } else { + category = CATEGORY_MISC; + itemId = vm->getRandomNumber(1, 9); + } + } + + XeenItem &newItem = _items[category][itemIndex]; + newItem.clear(); + newItem._id = itemId; + + v4 = vm->getRandomNumber(1, 100); + switch (category) { + case CATEGORY_WEAPON: + case CATEGORY_ARMOR: + if (p1 != 1) { + if (v4 <= 70) { + v8 = 3; + } else if (v4 <= 98) { + v8 = 1; + } else { + v8 = 2; + } + } + break; + + case CATEGORY_ACCESSORY: + if (v4 <= 20) { + v8 = 3; + } else if (v4 <= 60) { + v8 = 1; + } else { + v8 = 2; + } + break; + + case CATEGORY_MISC: + v8 = 4; + break; + } + + if (p1 != 1 || category == CATEGORY_MISC) { + int rval, mult; + switch (v8) { + case 1: + rval = vm->getRandomNumber(1, 100); + if (rval <= 25) { + mult = 0; + } + else if (rval <= 45) { + mult = 1; + } + else if (rval <= 60) { + mult = 2; + } + else if (rval <= 75) { + mult = 3; + } + else if (rval <= 95) { + mult = 4; + } + else { + mult = 5; + } + + v12 = MAKE_ITEM_ARR1[vm->getRandomNumber(MAKE_ITEM_ARR2[mult][p1][0], + MAKE_ITEM_ARR2[mult][p1][1])]; + break; + + case 2: + rval = vm->getRandomNumber(1, 100); + if (rval <= 15) { + mult = 0; + } + else if (rval <= 25) { + mult = 1; + } + else if (rval <= 35) { + mult = 2; + } + else if (mult <= 50) { + mult = 3; + } + else if (mult <= 65) { + mult = 4; + } + else if (mult <= 80) { + mult = 5; + } + else if (mult <= 85) { + mult = 6; + } + else if (mult <= 90) { + mult = 7; + } + else if (mult <= 95) { + mult = 8; + } + else { + mult = 9; + } + + v12 = MAKE_ITEM_ARR1[vm->getRandomNumber(MAKE_ITEM_ARR3[mult][p1][0], + MAKE_ITEM_ARR3[mult][p1][1])]; + break; + + case 3: + rval = p1 == 7 || vm->getRandomNumber(1, 100) > 70; + v16 = vm->getRandomNumber(MAKE_ITEM_ARR4[mult][p1][0], + MAKE_ITEM_ARR4[mult][p1][1]); + break; + + case 4: + miscBonus = vm->getRandomNumber(MAKE_ITEM_ARR5[p1][0], MAKE_ITEM_ARR5[p1][1]); + break; + + default: + break; + } + } + + switch (category) { + case CATEGORY_WEAPON: + if (p1 != 1) { + newItem._material = (v14 ? v14 + 58 : 0) + (v16 ? v16 + 36 : 0) + v12; + if (vm->getRandomNumber(20) == 10) + newItem._bonusFlags = vm->getRandomNumber(1, 6); + } + break; + + case CATEGORY_ARMOR: + case CATEGORY_ACCESSORY: + if (p1 != 1) { + newItem._material = (v14 ? v14 + 58 : 0) + (v16 ? v16 + 36 : 0) + v12; + } + break; + + case CATEGORY_MISC: + newItem._id = miscId; + newItem._bonusFlags = miscBonus; + break; + } + + return category; +} + + } // End of namespace Xeen diff --git a/engines/xeen/character.h b/engines/xeen/character.h index 6514caeaa1..af9f7c69e9 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -106,11 +106,13 @@ protected: public: InventoryItems(Character *character, ItemCategory category); + void clear(); + bool passRestrictions(int itemId, bool showError) const; Common::String getName(int itemIndex); - virtual Common::String getFullDescription(int itemIndex, int displayNum) = 0; + virtual Common::String getFullDescription(int itemIndex, int displayNum = 15) = 0; bool discardItem(int itemIndex); @@ -119,6 +121,8 @@ public: void removeItem(int itemIndex); void sort(); + + virtual void enchantItem(int itemIndex, int amount); }; class WeaponItems: public InventoryItems { @@ -128,6 +132,8 @@ public: virtual void equipItem(int itemIndex); virtual Common::String getFullDescription(int itemIndex, int displayNum); + + virtual void enchantItem(int itemIndex, int amount); }; class ArmorItems : public InventoryItems { @@ -137,6 +143,8 @@ public: virtual void equipItem(int itemIndex); virtual Common::String getFullDescription(int itemIndex, int displayNum); + + virtual void enchantItem(int itemIndex, int amount); }; class AccessoryItems : public InventoryItems { @@ -226,6 +234,9 @@ public: int _currentCombatSpell; public: Character(); + + void clear(); + void synchronize(Common::Serializer &s); Condition worstCondition() const; @@ -271,6 +282,8 @@ public: int getNumSkills() const; int getNumAwards() const; + + int makeItem(int p1, int itemIndex, int p3); }; } // End of namespace Xeen diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index beaf5652d7..46f07d4812 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -21,6 +21,7 @@ */ #include "xeen/dialogs_items.h" +#include "xeen/dialogs_query.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -41,7 +42,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { Screen &screen = *_vm->_screen; Character *startingChar = c; - ItemCategory category = mode == ITEMMODE_4 || mode == ITEMMODE_COMBAT ? + ItemCategory category = mode == ITEMMODE_RECHARGE || mode == ITEMMODE_COMBAT ? CATEGORY_MISC : CATEGORY_WEAPON; int varA = mode == ITEMMODE_COMBAT ? 1 : 0; if (varA != 0) @@ -57,13 +58,13 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { bool redrawFlag = true; while (!_vm->shouldQuit()) { if (redrawFlag) { - if ((mode != ITEMMODE_CHAR_INFO || category != CATEGORY_MISC) && mode != ITEMMODE_6 - && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) { + if ((mode != ITEMMODE_CHAR_INFO || category != CATEGORY_MISC) && mode != ITEMMODE_ENCHANT + && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) { _buttons[8]._bounds.moveTo(148, _buttons[8]._bounds.top); _buttons[9]._draw = false; - } else if (mode == ITEMMODE_4) { + } else if (mode == ITEMMODE_RECHARGE) { _buttons[4]._value = Common::KEYCODE_r; - } else if (mode == ITEMMODE_6) { + } else if (mode == ITEMMODE_ENCHANT) { _buttons[4]._value = Common::KEYCODE_e; } else if (mode == ITEMMODE_TO_GOLD) { _buttons[4]._value = Common::KEYCODE_g; @@ -75,17 +76,17 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { // Write text for the dialog Common::String msg; - if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_8 && mode != ITEMMODE_6 - && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) { + if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_8 && mode != ITEMMODE_ENCHANT + && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) { msg = Common::String::format(ITEMS_DIALOG_TEXT1, BTN_SELL, BTN_IDENTIFY, BTN_FIX); - } else if (mode != ITEMMODE_6 && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) { + } else if (mode != ITEMMODE_ENCHANT && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) { msg = Common::String::format(ITEMS_DIALOG_TEXT1, category == 3 ? BTN_USE : BTN_EQUIP, BTN_REMOVE, BTN_DISCARD, BTN_QUEST); - } else if (mode == ITEMMODE_6) { + } else if (mode == ITEMMODE_ENCHANT) { msg = Common::String::format(ITEMS_DIALOG_TEXT2, BTN_ENCHANT); - } else if (mode == ITEMMODE_4) { + } else if (mode == ITEMMODE_RECHARGE) { msg = Common::String::format(ITEMS_DIALOG_TEXT2, BTN_RECHARGE); } else { msg = Common::String::format(ITEMS_DIALOG_TEXT2, BTN_GOLD); @@ -103,7 +104,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { if (mode == ITEMMODE_CHAR_INFO || category != 3) { _iconSprites.draw(screen, 8, Common::Point(148, 109)); } - if (mode != ITEMMODE_6 && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) { + if (mode != ITEMMODE_ENCHANT && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) { _iconSprites.draw(screen, 10, Common::Point(182, 109)); _iconSprites.draw(screen, 12, Common::Point(216, 109)); _iconSprites.draw(screen, 14, Common::Point(250, 109)); @@ -138,7 +139,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { if (i._id) { if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8 - || mode == ITEMMODE_6 || mode == ITEMMODE_4) { + || mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) { lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, arr[idx], idx + 1, c->_items[category].getFullDescription(idx, arr[idx]))); @@ -178,8 +179,8 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { int skill = startingChar->_skills[MERCHANT]; if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8 - || mode == ITEMMODE_6 || mode == ITEMMODE_4) { - tempMode = ITEMMODE_6; + || mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) { + tempMode = ITEMMODE_ENCHANT; } else if (mode == ITEMMODE_TO_GOLD) { skill = 1; } @@ -227,14 +228,14 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { } case ITEMMODE_2: - case ITEMMODE_4: - case ITEMMODE_6: + case ITEMMODE_RECHARGE: + case ITEMMODE_ENCHANT: case ITEMMODE_9: case ITEMMODE_10: case ITEMMODE_TO_GOLD: screen._windows[30].writeString(Common::String::format(X_FOR_Y, CATEGORY_NAMES[category], startingChar->_name.c_str(), - (mode == ITEMMODE_4 || mode == ITEMMODE_6) ? CHARGES : COST, + (mode == ITEMMODE_RECHARGE || mode == ITEMMODE_ENCHANT) ? CHARGES : COST, lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(), lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(), lines[8].c_str() @@ -297,7 +298,7 @@ void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) { (mode == ITEMMODE_CHAR_INFO) ? "items" : "buy")); _equipSprites.load("equip.icn"); - if (mode == ITEMMODE_6 || mode == ITEMMODE_4 || mode == ITEMMODE_TO_GOLD) { + if (mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE || mode == ITEMMODE_TO_GOLD) { // Enchant button list addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_w, &_iconSprites); addButton(Common::Rect(46, 109, 70, 129), Common::KEYCODE_a, &_iconSprites); @@ -537,14 +538,16 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode, return (mode == ITEMMODE_CHAR_INFO) ? 0 : result; } -bool ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, ItemCategory category, +int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, ItemCategory category, ItemsMode mode) { Combat &combat = *_vm->_combat; EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; Party &party = *_vm->_party; Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; Spells &spells = *_vm->_spells; + bool isDarkCc = _vm->_files->_isDarkCc; XeenItem *itemCategories[4] = { &c._weapons[0], &c._armor[0], &c._accessories[0], &c._misc[0] }; XeenItem *items = itemCategories[category]; @@ -647,17 +650,116 @@ bool ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, It } } else { ErrorScroll::show(_vm, Common::String::format(NO_SPECIAL_ABILITIES, - c._items[category].getFullDescription(itemIndex, 15).c_str() + c._items[category].getFullDescription(itemIndex).c_str() )); } } } break; case 3: - // TODO: Remaining switches + c._items[category].discardItem(itemIndex); + break; default: break; } + break; + + case ITEMMODE_BLACKSMITH: { + InventoryItems &items = _oldCharacter->_items[category]; + if (items[INV_ITEMS_TOTAL - 1]._id) { + // If the last slot is in use, it means the list is full + ErrorScroll::show(_vm, Common::String::format(BACKPACK_IS_FULL, + _oldCharacter->_name.c_str())); + } else { + int cost = calcItemCost(_oldCharacter, itemIndex, mode, 0, category); + Common::String desc = c._items[category].getFullDescription(itemIndex); + if (Confirm::show(_vm, Common::String::format(BUY_X_FOR_Y_GOLD, + desc.c_str(), cost))) { + if (party.subtract(0, cost, 0, WT_FREEZE_WAIT)) { + if (isDarkCc) { + sound.playSample(0, 0); + File f("choice2.voc"); + sound.playSample(&f, 0); + } + + // Add entry to the end of the list + _oldCharacter->_items[category][8] = c._items[category][itemIndex]; + _oldCharacter->_items[category][8]._frame = 0; + c._items[category].clear(); + c._items[category].sort(); + _oldCharacter->_items[category].sort(); + } + } + } + return 0; + } + + case ITEMMODE_2: { + XeenItem &item = c._items[category][itemIndex]; + bool noNeed; + switch (category) { + case CATEGORY_WEAPON: + noNeed = (item._bonusFlags & ITEMFLAG_CURSED) || item._id == 34; + break; + default: + noNeed = item._bonusFlags & ITEMFLAG_CURSED; + break; + } + + if (noNeed) { + ErrorScroll::show(_vm, Common::String::format(NO_NEED_OF_THIS, + c._items[category].getFullDescription(itemIndex).c_str())); + } else { + int cost = calcItemCost(&c, itemIndex, mode, c._skills[MERCHANT], category); + Common::String desc = c._items[category].getFullDescription(itemIndex); + Common::String msg = Common::String::format(SELL_X_FOR_Y_GOLD, + desc.c_str(), cost); + + if (Confirm::show(_vm, msg)) { + // Remove the sold item and add gold to the party's total + item.clear(); + c._items[category].sort(); + + party._gold += cost; + } + } + return 0; + } + + case ITEMMODE_RECHARGE: + if (category != CATEGORY_MISC || c._misc[itemIndex]._material > 9 + || c._misc[itemIndex]._id == 53 || c._misc[itemIndex]._id == 0) { + sound.playFX(21); + ErrorScroll::show(_vm, Common::String::format(NOT_RECHARGABLE, SPELL_FAILED)); + } else { + int charges = MIN(63, _vm->getRandomNumber(1, 6) + + (c._misc[itemIndex]._bonusFlags & ITEMFLAG_BONUS_MASK)); + sound.playFX(20); + + c._misc[itemIndex]._bonusFlags = (c._misc[itemIndex]._bonusFlags + & ~ITEMFLAG_BONUS_MASK) | charges; + } + return 2; + + case ITEMMODE_ENCHANT: { + Character *ps = &_itemsCharacter; + ps->clear(); + int charges = _vm->getRandomNumber(1, _oldCharacter->getCurrentLevel() / 5 + 1); + charges = MIN(charges, 5); + + switch (category) { + case CATEGORY_WEAPON: + + default: + break; + } + + // TODO + return 2; + } + + default: + break; } } diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h index aff43f6429..dab26e6f82 100644 --- a/engines/xeen/dialogs_items.h +++ b/engines/xeen/dialogs_items.h @@ -31,7 +31,7 @@ namespace Xeen { enum ItemsMode { ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_2 = 2, ITEMMODE_3 = 3, - ITEMMODE_4 = 4, ITEMMODE_5 = 5, ITEMMODE_6 = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, + ITEMMODE_RECHARGE = 4, ITEMMODE_5 = 5, ITEMMODE_ENCHANT = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, ITEMMODE_9 = 9, ITEMMODE_10 = 10, ITEMMODE_TO_GOLD = 11 }; @@ -58,7 +58,7 @@ private: int calcItemCost(Character *c, int itemIndex, ItemsMode mode, int skillLevel, ItemCategory category); - bool doItemOptions(Character &c, int actionIndex, int itemIndex, + int doItemOptions(Character &c, int actionIndex, int itemIndex, ItemCategory category, ItemsMode mode); public: static Character *show(XeenEngine *vm, Character *c, ItemsMode mode); diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 0f6588af9a..23eac4f1a2 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -596,6 +596,41 @@ const int METAL_LAC[9] = { -3, 0, -2, -1, 1, 2, 4, 6, 8 }; const int ARMOR_STRENGTHS[14] = { 0, 2, 4, 5, 6, 7, 8, 10, 4, 2, 1, 1, 1, 1 }; +const int MAKE_ITEM_ARR1[6] = { 0, 8, 15, 20, 25, 33 }; + +const int MAKE_ITEM_ARR2[6][7][2] = { + { { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } }, + { { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 6, 7 }, { 7, 7 } }, + { { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 5 }, { 5, 5 } }, + { { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 5 }, { 5, 5 } }, + { { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } }, + { { 0, 0 }, { 1, 1 }, { 1, 1 }, { 1, 2 }, { 2, 2 }, { 2, 3 }, { 3, 3 } } +}; + +const int MAKE_ITEM_ARR3[10][7][2] = { + { { 0, 0 }, { 1, 4 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 6, 10 }, { 10, 10 } }, + { { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } }, + { { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } }, + { { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } }, + { { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, { 6, 6 } }, + { { 0, 0 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 5 }, { 5, 6 }, { 6, 6 } }, + { { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 5 }, { 5, 5 } }, + { { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, { 6, 6 } }, + { { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 5 }, { 5, 5 } }, + { { 0, 0 }, { 1, 2 }, { 1, 4 }, { 3, 6 }, { 5, 8 }, { 7, 10 }, { 10, 10 } } +}; + +const int MAKE_ITEM_ARR4[2][7][2] = { + { { 0, 0 }, { 1, 4 }, { 3, 7 }, { 4, 8 }, { 5, 9 }, { 8, 9 }, { 9, 9 } }, + { { 0, 0 }, { 1, 4 }, { 2, 6 }, { 4, 7 }, { 6, 10 }, { 9, 13 }, { 13, 13 } } +}; + + +const int MAKE_ITEM_ARR5[8][2] = { + { 0, 0 }, { 1, 15 }, { 16, 30 }, { 31, 40 }, { 41, 50 }, + { 51, 60 }, { 61, 73 }, { 61, 73 } +}; + const int OUTDOOR_DRAWSTRCT_INDEXES[44] = { 37, 38, 39, 40, 41, 44, 42, 43, 47, 45, 46, 48, 49, 52, 50, 51, 66, 67, 68, 69, 70, 71, @@ -1146,4 +1181,18 @@ const char *const CANNOT_DISCARD_CURSED_ITEM = "\3x""cYou cannot discard a curse const char *const PERMANENTLY_DISCARD = "\v000\t000\x03lPermanently discard %s\fd?"; +const char *const BACKPACK_IS_FULL = "\v005\x03c\fd%s's backpack is full."; + +const char *const BUY_X_FOR_Y_GOLD = "\x3l\v000\t000\fdBuy %s\fd for %lu gold?"; + +const char *const SELL_X_FOR_Y_GOLD = "\x3l\v000\t000\fdSell %s\fd for %lu gold?"; + +const char *const NO_NEED_OF_THIS = "\v005\x03c\fdWe have no need of this %s\f!"; + +const char *const NOT_RECHARGABLE = "\v012\x03c\fdNot Rechargeable. %s"; + +const char *const NOT_ENCHANTABLE = "\v012\t000\x03cNot Enchantable. %s"; + +const char *const SPELL_FAILED = "Spell Failed!"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 87b9468064..6e757bc00c 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -176,6 +176,16 @@ extern const int METAL_LAC[9]; extern const int ARMOR_STRENGTHS[14]; +extern const int MAKE_ITEM_ARR1[6]; + +extern const int MAKE_ITEM_ARR2[6][7][2]; + +extern const int MAKE_ITEM_ARR3[10][7][2]; + +extern const int MAKE_ITEM_ARR4[2][7][2]; + +extern const int MAKE_ITEM_ARR5[8][2]; + extern const int OUTDOOR_DRAWSTRCT_INDEXES[44]; extern const int TOWN_MAXES[2][11]; @@ -420,6 +430,20 @@ extern const char *const CANNOT_DISCARD_CURSED_ITEM; extern const char *const PERMANENTLY_DISCARD; +extern const char *const BACKPACK_IS_FULL; + +extern const char *const BUY_X_FOR_Y_GOLD; + +extern const char *const SELL_X_FOR_Y_GOLD; + +extern const char *const NO_NEED_OF_THIS; + +extern const char *const NOT_RECHARGABLE; + +extern const char *const SPELL_FAILED; + +extern const char *const NOT_ENCHANTABLE; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 59f202e461..d51cd0c26b 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -140,7 +140,6 @@ class Scripts { private: XeenEngine *_vm; int _charFX[6]; - int _itemType; int _treasureItems; int _treasureGold; int _treasureGems; @@ -229,6 +228,7 @@ public: bool _eventSkipped; int _whoWill; int _nEdamageType; + int _itemType; Common::Array<MirrorEntry> _mirror; public: Scripts(XeenEngine *vm); -- cgit v1.2.3 From 5ffbe2de873e6ac789ce9eff298a4ab21d02196b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Feb 2015 11:45:20 -0500 Subject: XEEN: Implemented getIdentifiedDetails and getAttributes --- engines/xeen/character.cpp | 165 ++++++++++++++++++++++++++++++++++++++--- engines/xeen/character.h | 27 ++++++- engines/xeen/dialogs_items.cpp | 86 +++++++++++++++------ engines/xeen/dialogs_items.h | 2 +- engines/xeen/party.h | 2 +- engines/xeen/resources.cpp | 86 +++++++++++++++++++++ engines/xeen/resources.h | 28 +++++++ engines/xeen/spells.h | 28 +++++++ 8 files changed, 386 insertions(+), 38 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index 3489783983..cde244b051 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -44,21 +44,21 @@ void XeenItem::synchronize(Common::Serializer &s) { s.syncAsByte(_frame); } -int XeenItem::getElementalCategory() const { +ElementalCategory XeenItem::getElementalCategory() const { int idx; for (idx = 0; ELEMENTAL_CATEGORIES[idx] < _material; ++idx) ; - return idx; + return (ElementalCategory)idx; } -int XeenItem::getAttributeCategory() const { +AttributeCategory XeenItem::getAttributeCategory() const { int m = _material - 59; int idx; for (idx = 0; ATTRIBUTE_CATEGORIES[idx] < m; ++idx) ; - return idx; + return (AttributeCategory)idx; } /*------------------------------------------------------------------------*/ @@ -125,6 +125,24 @@ Common::String InventoryItems::getName(int itemIndex) { return _names[id]; } +Common::String InventoryItems::getIdentifiedDetails(int itemIndex) { + XeenItem &item = operator[](itemIndex); + + Common::String classes; + for (int charClass = CLASS_KNIGHT; charClass <= CLASS_RANGER; ++charClass) { + if (passRestrictions(charClass, true)) { + const char *const name = CLASS_NAMES[charClass]; + classes += name[0]; + classes += name[1]; + classes += " "; + } + } + if (classes.size() == 30) + classes = ALL; + + return getAttributes(item, classes); +} + /** * Discard an item from the inventory */ @@ -301,6 +319,53 @@ void WeaponItems::enchantItem(int itemIndex, int amount) { } } +/* + * Returns a text string listing all the stats/attributes of a given item + */ +Common::String WeaponItems::getAttributes(XeenItem &item, const Common::String &classes) { + Common::String attrBonus, elemDamage, physDamage, toHit, specialPower; + attrBonus = elemDamage = physDamage = toHit = specialPower = FIELD_NONE; + + // First calculate physical damage + int minVal = WEAPON_DAMAGE_BASE[item._id]; + int maxVal = minVal * WEAPON_DAMAGE_MULTIPLIER[item._id]; + + if (item._material >= 37 && item._material <= 58) { + minVal += METAL_DAMAGE[item._material - 37]; + maxVal += METAL_DAMAGE[item._material - 37]; + toHit = Common::String::format("%+d", METAL_DAMAGE_PERCENT[item._material - 37]); + } + + physDamage = Common::String::format(DAMAGE_X_TO_Y, minVal, maxVal); + + // Next handle elemental/attribute damage + if (item._material < 37) { + int damage = ELEMENTAL_DAMAGE[item._material]; + if (damage > 0) { + ElementalCategory elemCategory = item.getElementalCategory(); + elemDamage = Common::String::format(ELEMENTAL_XY_DAMAGE, + damage, ELEMENTAL_NAMES[elemCategory]); + } + } else if (item._material >= 59) { + int bonus = ATTRIBUTE_BONUSES[item._material - 59]; + AttributeCategory attrCategory = item.getAttributeCategory(); + attrBonus = Common::String::format(ATTR_XY_BONUS, bonus, + ATTRIBUTE_NAMES[attrCategory]); + } + + // Handle weapon effective against + int effective = item._bonusFlags & ITEMFLAG_BONUS_MASK; + if (effective) { + specialPower = Common::String::format(EFFECTIVE_AGAINST, + EFFECTIVENESS_NAMES[effective]); + } + + return Common::String::format(ITEM_DETAILS, classes.c_str(), + toHit.c_str(), physDamage.c_str(), elemDamage.c_str(), + FIELD_NONE, FIELD_NONE, attrBonus.c_str(), specialPower.c_str() + ); +} + /*------------------------------------------------------------------------*/ /** @@ -419,6 +484,41 @@ void ArmorItems::enchantItem(int itemIndex, int amount) { } } +/* +* Returns a text string listing all the stats/attributes of a given item +*/ +Common::String ArmorItems::getAttributes(XeenItem &item, const Common::String &classes) { + Common::String elemResist, attrBonus, acBonus; + elemResist = attrBonus = acBonus = FIELD_NONE; + + if (item._material < 36) { + int resistence = ELEMENTAL_RESISTENCES[item._material]; + if (resistence > 0) { + int eCategory = ELEM_FIRE; + while (eCategory < ELEM_MAGIC && ELEMENTAL_CATEGORIES[eCategory] < item._material) + ++eCategory; + + elemResist = Common::String::format(ATTR_XY_BONUS, resistence, + ELEMENTAL_NAMES[eCategory]); + } + } else if (item._material >= 59) { + int bonus = ATTRIBUTE_BONUSES[item._material - 59]; + AttributeCategory aCategory = item.getAttributeCategory(); + attrBonus = Common::String::format(ATTR_XY_BONUS, bonus, + ATTRIBUTE_NAMES[aCategory]); + } + + int strength = ARMOR_STRENGTHS[item._id]; + if (item._material >= 37 && item._material <= 58) { + strength += METAL_LAC[item._material - 37]; + } + acBonus = Common::String::format("%+d", strength); + + return Common::String::format(ITEM_DETAILS, classes.c_str(), + FIELD_NONE, FIELD_NONE, FIELD_NONE, + elemResist.c_str(), acBonus.c_str(), attrBonus.c_str(), FIELD_NONE); +} + /*------------------------------------------------------------------------*/ /** @@ -490,6 +590,35 @@ Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum) ); } +/* +* Returns a text string listing all the stats/attributes of a given item +*/ +Common::String AccessoryItems::getAttributes(XeenItem &item, const Common::String &classes) { + Common::String elemResist, attrBonus; + elemResist = attrBonus = FIELD_NONE; + + if (item._material < 36) { + int resistence = ELEMENTAL_RESISTENCES[item._material]; + if (resistence > 0) { + int eCategory = ELEM_FIRE; + while (eCategory < ELEM_MAGIC && ELEMENTAL_CATEGORIES[eCategory] < item._material) + ++eCategory; + + elemResist = Common::String::format(ATTR_XY_BONUS, resistence, + ELEMENTAL_NAMES[eCategory]); + } + } else if (item._material >= 59) { + int bonus = ATTRIBUTE_BONUSES[item._material - 59]; + AttributeCategory aCategory = item.getAttributeCategory(); + attrBonus = Common::String::format(ATTR_XY_BONUS, bonus, + ATTRIBUTE_NAMES[aCategory]); + } + + return Common::String::format(ITEM_DETAILS, classes.c_str(), + FIELD_NONE, FIELD_NONE, FIELD_NONE, + elemResist.c_str(), FIELD_NONE, attrBonus.c_str(), FIELD_NONE); +} + /*------------------------------------------------------------------------*/ /** @@ -510,6 +639,22 @@ Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) { ); } + +/* +* Returns a text string listing all the stats/attributes of a given item +*/ +Common::String MiscItems::getAttributes(XeenItem &item, const Common::String &classes) { + Common::String specialPower = FIELD_NONE; + Spells &spells = *vm()->_spells; + + if (item._id) { + specialPower = spells._spellNames[MISC_SPELL_INDEX[item._id]]; + } + + return Common::String::format(ITEM_DETAILS, classes.c_str(), + FIELD_NONE, FIELD_NONE, FIELD_NONE, FIELD_NONE, FIELD_NONE, + FIELD_NONE, specialPower.c_str()); +} /*------------------------------------------------------------------------*/ InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor, @@ -975,8 +1120,8 @@ int Character::itemScan(int itemId) const { if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) { - int mIndex = item.getAttributeCategory(); - if (mIndex > 2) + int mIndex = (int)item.getAttributeCategory(); + if (mIndex > PERSONALITY) ++mIndex; if (mIndex == itemId) @@ -991,8 +1136,8 @@ int Character::itemScan(int itemId) const { if (item._frame && !(item._bonusFlags & 0xC0)) { if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) { - int mIndex = item.getAttributeCategory(); - if (mIndex > 2) + int mIndex = (int)item.getAttributeCategory(); + if (mIndex > PERSONALITY) ++mIndex; if (mIndex == itemId) @@ -1023,8 +1168,8 @@ int Character::itemScan(int itemId) const { if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11 && itemId != 3) { if (item._material >= 59 && item._material <= 130) { - int mIndex = item.getAttributeCategory(); - if (mIndex > 2) + int mIndex = (int)item.getAttributeCategory(); + if (mIndex > PERSONALITY) ++mIndex; if (mIndex == itemId) { diff --git a/engines/xeen/character.h b/engines/xeen/character.h index af9f7c69e9..6e6a77210e 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -73,6 +73,17 @@ enum Condition { NO_CONDITION = 16 }; +enum ElementalCategory { + ELEM_FIRE = 0, ELEM_ELECTRICITY = 1, ELEM_COLD = 2, + ELEM_ACID_POISON = 3, ELEM_ENERGY = 4, ELEM_MAGIC = 5 +}; + +enum AttributeCategory { + ATTR_MIGHT = 0, ATTR_INTELLECT = 1, ATTR_PERSONALITY = 2, ATTR_SPEED = 3, + ATTR_ACCURACY = 4, ATTR_LUCK = 5, ATTR_HIT_POINTS = 6, ATTR_SPELL_POINTS = 7, + ATTR_ARMOR_CLASS = 8, ATTR_THIEVERY = 9 +}; + class XeenEngine; class Character; @@ -89,9 +100,9 @@ public: void synchronize(Common::Serializer &s); - int getElementalCategory() const; + ElementalCategory getElementalCategory() const; - int getAttributeCategory() const; + AttributeCategory getAttributeCategory() const; }; class InventoryItems : public Common::Array<XeenItem> { @@ -103,6 +114,8 @@ protected: XeenEngine *vm(); void equipError(int itemIndex1, ItemCategory category1, int itemIndex2, ItemCategory category2); + + virtual Common::String getAttributes(XeenItem &item, const Common::String &classes) = 0; public: InventoryItems(Character *character, ItemCategory category); @@ -114,6 +127,8 @@ public: virtual Common::String getFullDescription(int itemIndex, int displayNum = 15) = 0; + Common::String getIdentifiedDetails(int itemIndex); + bool discardItem(int itemIndex); virtual void equipItem(int itemIndex) {} @@ -126,6 +141,8 @@ public: }; class WeaponItems: public InventoryItems { +protected: + virtual Common::String getAttributes(XeenItem &item, const Common::String &classes); public: WeaponItems(Character *character) : InventoryItems(character, CATEGORY_WEAPON) {} @@ -137,6 +154,8 @@ public: }; class ArmorItems : public InventoryItems { +protected: + virtual Common::String getAttributes(XeenItem &item, const Common::String &classes); public: ArmorItems(Character *character) : InventoryItems(character, CATEGORY_ARMOR) {} @@ -148,6 +167,8 @@ public: }; class AccessoryItems : public InventoryItems { +protected: + virtual Common::String getAttributes(XeenItem &item, const Common::String &classes); public: AccessoryItems(Character *character) : InventoryItems(character, CATEGORY_ACCESSORY) {} @@ -157,6 +178,8 @@ public: }; class MiscItems : public InventoryItems { +protected: + virtual Common::String getAttributes(XeenItem &item, const Common::String &classes); public: MiscItems(Character *character) : InventoryItems(character, CATEGORY_MISC) {} diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index 46f07d4812..8466097691 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -117,10 +117,10 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { case ITEMMODE_BLACKSMITH: _iconSprites.draw(screen, 11, Common::Point(182, 109)); break; - case ITEMMODE_9: + case ITEMMODE_REPAIR: _iconSprites.draw(screen, 15, Common::Point(250, 109)); break; - case ITEMMODE_10: + case ITEMMODE_IDENTIFY: _iconSprites.draw(screen, 13, Common::Point(216, 109)); break; default: @@ -230,8 +230,8 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { case ITEMMODE_2: case ITEMMODE_RECHARGE: case ITEMMODE_ENCHANT: - case ITEMMODE_9: - case ITEMMODE_10: + case ITEMMODE_REPAIR: + case ITEMMODE_IDENTIFY: case ITEMMODE_TO_GOLD: screen._windows[30].writeString(Common::String::format(X_FOR_Y, CATEGORY_NAMES[category], startingChar->_name.c_str(), @@ -269,10 +269,10 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { case ITEMMODE_2: actionIndex = 1; break; - case ITEMMODE_9: + case ITEMMODE_REPAIR: actionIndex = 3; break; - case ITEMMODE_10: + case ITEMMODE_IDENTIFY: actionIndex = 2; break; default: @@ -448,10 +448,10 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode, case ITEMMODE_TO_GOLD: level = level == 0 ? 1 : 0; break; - case ITEMMODE_10: + case ITEMMODE_IDENTIFY: level = 2; break; - case ITEMMODE_9: + case ITEMMODE_REPAIR: level = 3; break; default: @@ -496,8 +496,8 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode, switch (mode) { case ITEMMODE_BLACKSMITH: case ITEMMODE_2: - case ITEMMODE_9: - case ITEMMODE_10: + case ITEMMODE_REPAIR: + case ITEMMODE_IDENTIFY: case ITEMMODE_TO_GOLD: result = (amount1 + amount2 + amount3 + amount4) / ITEM_SKILL_DIVISORS[level]; if (!result) @@ -518,8 +518,8 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode, switch (mode) { case ITEMMODE_BLACKSMITH: case ITEMMODE_2: - case ITEMMODE_9: - case ITEMMODE_10: + case ITEMMODE_REPAIR: + case ITEMMODE_IDENTIFY: case ITEMMODE_TO_GOLD: result = (amount1 + amount2 + amount3 + amount4) / ITEM_SKILL_DIVISORS[level]; if (!result) @@ -603,6 +603,8 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite } if (itemIndex != -1) { + XeenItem &item = c._items[category][itemIndex]; + switch (mode) { case ITEMMODE_CHAR_INFO: case ITEMMODE_8: @@ -695,7 +697,6 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite } case ITEMMODE_2: { - XeenItem &item = c._items[category][itemIndex]; bool noNeed; switch (category) { case CATEGORY_WEAPON: @@ -742,20 +743,57 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite return 2; case ITEMMODE_ENCHANT: { - Character *ps = &_itemsCharacter; - ps->clear(); - int charges = _vm->getRandomNumber(1, _oldCharacter->getCurrentLevel() / 5 + 1); - charges = MIN(charges, 5); - - switch (category) { - case CATEGORY_WEAPON: + int amount = _vm->getRandomNumber(1, _oldCharacter->getCurrentLevel() / 5 + 1); + amount = MIN(amount, 5); + _oldCharacter->_items[category].enchantItem(itemIndex, amount); + break; + } - default: - break; + case ITEMMODE_REPAIR: + if (!(item._bonusFlags & ITEMFLAG_BROKEN)) { + ErrorScroll::show(_vm, ITEM_NOT_BROKEN); + } else { + int cost = calcItemCost(&c, itemIndex, mode, actionIndex, category); + Common::String msg = Common::String::format(FIX_IDENTIFY_GOLD, + FIX_IDENTIFY[0], + c._items[category].getFullDescription(itemIndex), + cost); + + if (Confirm::show(_vm, msg) && party.subtract(0, cost, 0)) { + item._bonusFlags &= ~ITEMFLAG_BROKEN; + } } + break; - // TODO - return 2; + case ITEMMODE_IDENTIFY: { + int cost = calcItemCost(&c, itemIndex, mode, actionIndex, category); + Common::String msg = Common::String::format(FIX_IDENTIFY_GOLD, + FIX_IDENTIFY[1], + c._items[category].getFullDescription(itemIndex), + cost); + + if (Confirm::show(_vm, msg) && party.subtract(0, cost, 0)) { + Common::String details = c._items[category].getIdentifiedDetails(itemIndex); + Common::String desc = c._items[category].getFullDescription(itemIndex); + Common::String msg = Common::String::format(IDENTIFY_ITEM_MSG, + desc.c_str(), details.c_str()); + + Window &w = screen._windows[14]; + w.open(); + w.writeString(msg); + w.update(); + + saveButtons(); + clearButtons(); + + while (!_vm->shouldQuit() && !events.isKeyMousePressed()) + events.pollEventsAndWait(); + events.clearEvents(); + + restoreButtons(); + w.close(); + } + break; } default: diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h index dab26e6f82..42fe0158dc 100644 --- a/engines/xeen/dialogs_items.h +++ b/engines/xeen/dialogs_items.h @@ -32,7 +32,7 @@ namespace Xeen { enum ItemsMode { ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_2 = 2, ITEMMODE_3 = 3, ITEMMODE_RECHARGE = 4, ITEMMODE_5 = 5, ITEMMODE_ENCHANT = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, - ITEMMODE_9 = 9, ITEMMODE_10 = 10, ITEMMODE_TO_GOLD = 11 + ITEMMODE_REPAIR = 9, ITEMMODE_IDENTIFY = 10, ITEMMODE_TO_GOLD = 11 }; class ItemsDialog : public ButtonContainer { diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 8da1163a5f..ec7a8b99e1 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -142,7 +142,7 @@ public: void handleLight(); - int subtract(int mode, uint amount, int whereId, ErrorWaitType wait); + int subtract(int mode, uint amount, int whereId, ErrorWaitType wait = WT_FREEZE_WAIT); void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait); }; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 23eac4f1a2..55060c8743 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -592,6 +592,28 @@ const int ELEMENTAL_DAMAGE[37] = { 2, 4, 8, 16, 32, 2, 3, 4, 5, 10, 15, 20, 30, 5, 10, 25 }; +const int WEAPON_DAMAGE_BASE[35] = { + 0, 3, 2, 3, 2, 2, 4, 1, 2, 4, 2, 3, + 2, 2, 1, 1, 1, 1, 4, 4, 3, 2, 4, 2, + 2, 2, 5, 3, 3, 3, 3, 5, 4, 2, 6 +}; + +const int WEAPON_DAMAGE_MULTIPLIER[35] = { + 0, 3, 3, 4, 5, 4, 2, 3, 3, 3, 3, 3, + 2, 4, 10, 6, 8, 9, 4, 3, 6, 8, 5, 6, + 4, 5, 3, 5, 6, 7, 2, 2, 2, 2, 4 +}; + +const int METAL_DAMAGE[22] = { + -3, -6, -4, -2, 2, 4, 6, 8, 10, 0, 1, + 1, 2, 2, 3, 4, 5, 12, 15, 20, 30, 50 +}; + +const int METAL_DAMAGE_PERCENT[22] = { + 253, 252, 3, 2, 1, 2, 3, 4, 6, 0, 1, + 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10 +}; + const int METAL_LAC[9] = { -3, 0, -2, -1, 1, 2, 4, 6, 8 }; const int ARMOR_STRENGTHS[14] = { 0, 2, 4, 5, 6, 7, 8, 10, 4, 2, 1, 1, 1, 1 }; @@ -791,6 +813,28 @@ const char *const GUILD_OPTIONS = "\x03l\x09""000\x0B""090Gold" "\x03r\x09""000%s\x02\x03""c\x0B""122\x09""040ESC\x01"; +const int MISC_SPELL_INDEX[74] = { + NO_SPELL, MS_Light, MS_Awaken, MS_MagicArrow, + MS_FirstAid, MS_FlyingFist, MS_EnergyBlast, MS_Sleep, + MS_Revitalize, MS_CureWounds, MS_Sparks, MS_Shrapmetal, + MS_InsectSpray, MS_ToxicCloud, MS_ProtFromElements, MS_Pain, + MS_Jump, MS_BeastMaster, MS_Clairvoyance, MS_TurnUndead, + MS_Levitate, MS_WizardEye, MS_Bless, MS_IdentifyMonster, + MS_LightningBolt, MS_HolyBonus, MS_PowerCure, MS_NaturesCure, + MS_LloydsBeacon, MS_PowerShield, MS_Heroism, MS_Hynotize, + MS_WalkOnWater, MS_FrostBite, MS_DetectMonster, MS_FireBall, + MS_ColdRay, MS_CurePoison, MS_AcidSpray, MS_TimeDistortion, + MS_DragonSleep, MS_CureDisease, MS_Teleport, MS_FingerOfDeath, + MS_CureParalysis, MS_GolemStopper, MS_PoisonVolley, MS_DeadlySwarm, + MS_SuperShelter, MS_DayOfProtection, MS_DayOfSorcery, MS_CreateFood, + MS_FieryFlail, MS_RechargeItem, MS_FantasticFreeze, MS_TownPortal, + MS_StoneToFlesh, MS_RaiseDead, MS_Etheralize, MS_DancingSword, + MS_MoonRay, MS_MassDistortion, MS_PrismaticLight, MS_EnchantItem, + MS_Incinerate, MS_HolyWord, MS_Resurrection, MS_ElementalStorm, + MS_MegaVolts, MS_Inferno, MS_SunRay, MS_Implosion, + MS_StarBurst, MS_DivineIntervention +}; + const int SPELL_COSTS[77] = { 8, 1, 5, -2, 5, -2, 20, 10, 12, 8, 3, - 3, 75, 40, 12, 6, 200, 10, 100, 30, -1, 30, @@ -1087,6 +1131,19 @@ const char *const MISC_NAMES[22] = { "bogus", "bogus", "bogus", "bogus" }; +const char *const ELEMENTAL_NAMES[6] = { + "Fire", "Elec", "Cold", "Acid/Poison", "Energy", "Magic" +}; + +const char *const ATTRIBUTE_NAMES[10] = { + "might", "Intellect", "Personality", "Speed", "accuracy", "Luck", + "Hit Points", "Spell Points", "Armor Class", "Thievery" +}; + +const char *const EFFECTIVENESS_NAMES[7] = { + nullptr, "Dragons", "Undead", "Golems", "Bugs", "Monsters", "Beasts" +}; + const int WEAPON_BASE_COSTS[35] = { 0, 50, 15, 100, 80, 40, 60, 1, 10, 150, 30, 60, 8, 50, 100, 15, 30, 15, 200, 80, 250, 150, 400, 100, 40, 120, @@ -1195,4 +1252,33 @@ const char *const NOT_ENCHANTABLE = "\v012\t000\x03cNot Enchantable. %s"; const char *const SPELL_FAILED = "Spell Failed!"; +const char *const ITEM_NOT_BROKEN = "\fdThat item is not broken!"; + +const char *const FIX_IDENTIFY[2] = { "Fix", "Identify" }; + +const char *const FIX_IDENTIFY_GOLD = "\x3l\v000\t000%s %s\fd for %lu gold?"; + +const char *const IDENTIFY_ITEM_MSG = "\fd\v000\t000\x3""cIdentify Item\x3l\n" + "\n" + "\v012%s\fd\n" + "\n" + "%s"; + +const char *const ITEM_DETAILS = + "Proficient Classes\t132:\t140%s\n" + "to Hit Modifier\t132:\t140%s\n" + "Physical Damage\t132:\t140%s\n" + "Elemental Damage\t132:\t140%s\n" + "Elemental Resistance\t132:\t140%s\n" + "Armor Class Bonus\t132:\t140%s\n" + "Attribute Bonus\t132:\t140%s\n" + "Special Power\t132:\t140%s"; + +const char *const ALL = "All"; +const char *const FIELD_NONE = "None"; +const char *const DAMAGE_X_TO_Y = "%d to %d"; +const char *const ELEMENTAL_XY_DAMAGE = "%+d %s Damage"; +const char *const ATTR_XY_BONUS = "%+d %s"; +const char *const EFFECTIVE_AGAINST = "x3 vs %s"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 6e757bc00c..cab2af7c43 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/str-array.h" #include "gui/debugger.h" +#include "xeen/spells.h" namespace Xeen { @@ -172,6 +173,11 @@ extern const int ELEMENTAL_RESISTENCES[37]; extern const int ELEMENTAL_DAMAGE[37]; +extern const int WEAPON_DAMAGE_BASE[35]; +extern const int WEAPON_DAMAGE_MULTIPLIER[35]; +extern const int METAL_DAMAGE[22]; +extern const int METAL_DAMAGE_PERCENT[22]; + extern const int METAL_LAC[9]; extern const int ARMOR_STRENGTHS[14]; @@ -250,6 +256,8 @@ extern const char *const BUY_SPELLS; extern const char *const GUILD_OPTIONS; +extern const int MISC_SPELL_INDEX[74]; + extern const int SPELL_COSTS[77]; extern const int CLOUDS_SPELL_OFFSETS[5][20]; @@ -376,6 +384,9 @@ extern const char *const WEAPON_NAMES[35]; extern const char *const ARMOR_NAMES[14]; extern const char *const ACCESSORY_NAMES[11]; extern const char *const MISC_NAMES[22]; +extern const char *const ELEMENTAL_NAMES[6]; +extern const char *const ATTRIBUTE_NAMES[10]; +extern const char *const EFFECTIVENESS_NAMES[7]; extern const int WEAPON_BASE_COSTS[35]; extern const int ARMOR_BASE_COSTS[25]; @@ -444,6 +455,23 @@ extern const char *const SPELL_FAILED; extern const char *const NOT_ENCHANTABLE; +extern const char *const ITEM_NOT_BROKEN; + +extern const char *const FIX_IDENTIFY[2]; + +extern const char *const FIX_IDENTIFY_GOLD; + +extern const char *const IDENTIFY_ITEM_MSG; + +extern const char *const ITEM_DETAILS; + +extern const char *const ALL; +extern const char *const FIELD_NONE; +extern const char *const DAMAGE_X_TO_Y; +extern const char *const ELEMENTAL_XY_DAMAGE; +extern const char *const ATTR_XY_BONUS; +extern const char *const EFFECTIVE_AGAINST; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h index c2f9737c80..15389be599 100644 --- a/engines/xeen/spells.h +++ b/engines/xeen/spells.h @@ -32,6 +32,34 @@ class XeenEngine; #define MAX_SPELLS_PER_CLASS 40 +enum MagicSpell { + MS_AcidSpray = 0, MS_Awaken = 1, MS_BeastMaster = 2, MS_Bless = 3, + MS_Clairvoyance = 4, MS_ColdRay = 5, MS_CreateFood = 6, + MS_CureDisease = 7, MS_CureParalysis = 8, MS_CurePoison = 9, + MS_CureWounds = 10, MS_DancingSword = 11, MS_DayOfProtection = 12, + MS_DayOfSorcery = 13, MS_DeadlySwarm = 14, MS_DetectMonster = 15, + MS_DivineIntervention = 16, MS_DragonSleep = 17, MS_ElementalStorm = 18, + MS_EnchantItem = 19, MS_EnergyBlast = 20, MS_Etheralize = 21, + MS_FantasticFreeze = 22, MS_FieryFlail = 23, MS_FingerOfDeath = 24, + MS_FireBall = 25, MS_FirstAid = 26, MS_FlyingFist = 27, + MS_FrostBite = 28, MS_GolemStopper = 29, MS_Heroism = 30, + MS_HolyBonus = 31, MS_HolyWord = 32, MS_Hynotize = 33, + MS_IdentifyMonster = 34, MS_Implosion = 35, MS_Incinerate = 36, + MS_Inferno = 37, MS_InsectSpray = 38, MS_ItemToGold = 39, + MS_Jump = 40, MS_Levitate = 41, MS_Light = 42, MS_LightningBolt = 43, + MS_LloydsBeacon = 44, MS_MagicArrow = 45, MS_MassDistortion = 46, + MS_MegaVolts = 47, MS_MoonRay = 48, MS_NaturesCure = 49, MS_Pain = 50, + MS_PoisonVolley = 51, MS_PowerCure = 52, MS_PowerShield = 53, + MS_PrismaticLight = 54, MS_ProtFromElements = 55, MS_RaiseDead = 56, + MS_RechargeItem = 57, MS_Resurrection = 58, MS_Revitalize = 59, + MS_Shrapmetal = 60, MS_Sleep = 61, MS_Sparks = 62, MS_StarBurst = 63, + MS_StoneToFlesh = 64, MS_SunRay = 65, MS_SuperShelter = 66, + MS_SuppressDisease = 67, MS_SuppressPoison = 68, MS_Teleport = 69, + MS_TimeDistortion = 70, MS_TownPortal = 71, MS_ToxicCloud = 72, + MS_TurnUndead = 73, MS_WalkOnWater = 74, MS_WizardEye = 75, + NO_SPELL = 76 +}; + class Spells { private: XeenEngine *_vm; -- cgit v1.2.3 From 4bd128be7f799719cca87b5cac3966ee042ac769 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Feb 2015 12:04:39 -0500 Subject: XEEN: Finished doItemOptions --- engines/xeen/dialogs_items.cpp | 30 +++++++++++++++++++++++++++++- engines/xeen/dialogs_items.h | 2 ++ 2 files changed, 31 insertions(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index 8466097691..bbfbd95045 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -552,7 +552,8 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite XeenItem *itemCategories[4] = { &c._weapons[0], &c._armor[0], &c._accessories[0], &c._misc[0] }; XeenItem *items = itemCategories[category]; if (!items[0]._id) - return false; + // Inventory is empty + return category == CATEGORY_MISC ? 0 : 2; Window &w = screen._windows[11]; SpriteResource escSprites; @@ -796,6 +797,11 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite break; } + case ITEMMODE_TO_GOLD: + // Convert item in inventory to gold + itemToGold(c, itemIndex, category, mode); + return 2; + default: break; } @@ -807,4 +813,26 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite return true; } +void ItemsDialog::itemToGold(Character &c, int itemIndex, ItemCategory category, + ItemsMode mode) { + XeenItem &item = c._items[category][itemIndex]; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + if (category == CATEGORY_WEAPON && item._id == 34) { + sound.playFX(21); + ErrorScroll::show(_vm, Common::String::format("\v012\t000\x03c%s", + SPELL_FAILED)); + } else if (item._id != 0) { + // There is a valid item present + // Calculate cost of item and add it to the party's total + int cost = calcItemCost(&c, itemIndex, mode, 1, category); + party._gold += cost; + + // Remove the item from the inventory + item.clear(); + c._items[category].sort(); + } +} + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h index 42fe0158dc..77b1540fbe 100644 --- a/engines/xeen/dialogs_items.h +++ b/engines/xeen/dialogs_items.h @@ -60,6 +60,8 @@ private: int doItemOptions(Character &c, int actionIndex, int itemIndex, ItemCategory category, ItemsMode mode); + + void itemToGold(Character &c, int itemIndex, ItemCategory category, ItemsMode mode); public: static Character *show(XeenEngine *vm, Character *c, ItemsMode mode); }; -- cgit v1.2.3 From b633704847f12b87b0d4287ef18282b7165a64d6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Feb 2015 15:27:53 -0500 Subject: XEEN: Implemented remainder of ItemsDialog --- engines/xeen/character.h | 2 + engines/xeen/dialogs_items.cpp | 539 +++++++++++++++++++++++++++++----------- engines/xeen/dialogs_items.h | 2 + engines/xeen/dialogs_quests.cpp | 40 +++ engines/xeen/dialogs_quests.h | 43 ++++ engines/xeen/module.mk | 1 + engines/xeen/resources.cpp | 7 + engines/xeen/resources.h | 2 + 8 files changed, 488 insertions(+), 148 deletions(-) create mode 100644 engines/xeen/dialogs_quests.cpp create mode 100644 engines/xeen/dialogs_quests.h (limited to 'engines/xeen') diff --git a/engines/xeen/character.h b/engines/xeen/character.h index 6e6a77210e..af9e331fb5 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -98,6 +98,8 @@ public: void clear(); + bool empty() const { return _id != 0; } + void synchronize(Common::Serializer &s); ElementalCategory getElementalCategory() const; diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index bbfbd95045..83e0dd23a0 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -22,6 +22,7 @@ #include "xeen/dialogs_items.h" #include "xeen/dialogs_query.h" +#include "xeen/dialogs_quests.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -47,7 +48,11 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { int varA = mode == ITEMMODE_COMBAT ? 1 : 0; if (varA != 0) mode = ITEMMODE_CHAR_INFO; - int varE = mode == 1 ? 1 : 0; + bool updateStock = mode == ITEMMODE_BLACKSMITH; + int itemIndex = -1; + Common::StringArray lines; + int arr[40]; + int actionIndex = -1; events.setCursor(0); loadButtons(mode, c); @@ -55,9 +60,9 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { screen._windows[29].open(); screen._windows[30].open(); - bool redrawFlag = true; + enum { REDRAW_NONE, REDRAW_TEXT, REDRAW_FULL } redrawFlag = REDRAW_FULL; while (!_vm->shouldQuit()) { - if (redrawFlag) { + if (redrawFlag == REDRAW_FULL) { if ((mode != ITEMMODE_CHAR_INFO || category != CATEGORY_MISC) && mode != ITEMMODE_ENCHANT && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) { _buttons[8]._bounds.moveTo(148, _buttons[8]._bounds.top); @@ -94,174 +99,177 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { screen._windows[29].writeString(msg); drawButtons(&screen); - } - Common::StringArray lines; - int arr[40]; - Common::fill(&arr[0], &arr[40], 0); - int var2 = -1; - - if (mode == ITEMMODE_CHAR_INFO || category != 3) { - _iconSprites.draw(screen, 8, Common::Point(148, 109)); - } - if (mode != ITEMMODE_ENCHANT && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) { - _iconSprites.draw(screen, 10, Common::Point(182, 109)); - _iconSprites.draw(screen, 12, Common::Point(216, 109)); - _iconSprites.draw(screen, 14, Common::Point(250, 109)); + Common::fill(&arr[0], &arr[40], 0); + itemIndex = -1; } - switch (mode) { - case ITEMMODE_CHAR_INFO: - _iconSprites.draw(screen, 9, Common::Point(148, 109)); - break; - case ITEMMODE_BLACKSMITH: - _iconSprites.draw(screen, 11, Common::Point(182, 109)); - break; - case ITEMMODE_REPAIR: - _iconSprites.draw(screen, 15, Common::Point(250, 109)); - break; - case ITEMMODE_IDENTIFY: - _iconSprites.draw(screen, 13, Common::Point(216, 109)); - break; - default: - break; - } + if (redrawFlag == REDRAW_TEXT || redrawFlag == REDRAW_FULL) { + lines.clear(); - for (int idx = 0; idx < 9; ++idx) { - _itemsDrawList[idx]._y = 10 + idx * 9; + if (mode == ITEMMODE_CHAR_INFO || category != 3) { + _iconSprites.draw(screen, 8, Common::Point(148, 109)); + } + if (mode != ITEMMODE_ENCHANT && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) { + _iconSprites.draw(screen, 10, Common::Point(182, 109)); + _iconSprites.draw(screen, 12, Common::Point(216, 109)); + _iconSprites.draw(screen, 14, Common::Point(250, 109)); + } - switch (category) { - case CATEGORY_WEAPON: - case CATEGORY_ARMOR: - case CATEGORY_ACCESSORY: { - XeenItem &i = (category == CATEGORY_WEAPON) ? c->_weapons[idx] : - ((category == CATEGORY_ARMOR) ? c->_armor[idx] : c->_accessories[idx]); - - if (i._id) { - if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8 - || mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) { - lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, - arr[idx], idx + 1, - c->_items[category].getFullDescription(idx, arr[idx]))); + switch (mode) { + case ITEMMODE_CHAR_INFO: + _iconSprites.draw(screen, 9, Common::Point(148, 109)); + break; + case ITEMMODE_BLACKSMITH: + _iconSprites.draw(screen, 11, Common::Point(182, 109)); + break; + case ITEMMODE_REPAIR: + _iconSprites.draw(screen, 15, Common::Point(250, 109)); + break; + case ITEMMODE_IDENTIFY: + _iconSprites.draw(screen, 13, Common::Point(216, 109)); + break; + default: + break; + } + + for (int idx = 0; idx < 9; ++idx) { + _itemsDrawList[idx]._y = 10 + idx * 9; + + switch (category) { + case CATEGORY_WEAPON: + case CATEGORY_ARMOR: + case CATEGORY_ACCESSORY: { + XeenItem &i = (category == CATEGORY_WEAPON) ? c->_weapons[idx] : + ((category == CATEGORY_ARMOR) ? c->_armor[idx] : c->_accessories[idx]); + + if (i._id) { + if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8 + || mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) { + lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, + arr[idx], idx + 1, + c->_items[category].getFullDescription(idx, arr[idx]))); + } else { + lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2, + arr[idx], idx + 1, + c->_items[category].getFullDescription(idx, arr[idx]), + calcItemCost(c, idx, mode, + mode == ITEMMODE_TO_GOLD ? 1 : startingChar->_skills[MERCHANT], + category) + )); + } + + DrawStruct &ds = _itemsDrawList[idx]; + ds._sprites = &_equipSprites; + if (c->_weapons.passRestrictions(i._id, true)) + ds._frame = i._frame; + else + ds._frame = 14; + } else if (_itemsDrawList[idx]._sprites == nullptr) { + lines.push_back(NO_ITEMS_AVAILABLE); + } + break; + } + + case CATEGORY_MISC: { + XeenItem &i = c->_misc[idx]; + _itemsDrawList[idx]._sprites = nullptr; + + if (i._material == 0) { + // No item + if (idx == 0) { + lines.push_back(NO_ITEMS_AVAILABLE); + } } else { + ItemsMode tempMode = mode; + int skill = startingChar->_skills[MERCHANT]; + + if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8 + || mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) { + tempMode = ITEMMODE_ENCHANT; + } else if (mode == ITEMMODE_TO_GOLD) { + skill = 1; + } + lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2, arr[idx], idx + 1, c->_items[category].getFullDescription(idx, arr[idx]), - calcItemCost(c, idx, mode, - mode == ITEMMODE_TO_GOLD ? 1 : startingChar->_skills[MERCHANT], - category) + calcItemCost(c, idx, tempMode, skill, category) )); } + break; + } - DrawStruct &ds = _itemsDrawList[idx]; - ds._sprites = &_equipSprites; - if (c->_weapons.passRestrictions(i._id, true)) - ds._frame = i._frame; - else - ds._frame = 14; - } else if (_itemsDrawList[idx]._sprites == nullptr) { - lines.push_back(NO_ITEMS_AVAILABLE); + default: + break; } - break; } + while (lines.size() < INV_ITEMS_TOTAL) + lines.push_back(""); - case CATEGORY_MISC: { - XeenItem &i = c->_misc[idx]; - _itemsDrawList[idx]._sprites = nullptr; + // Draw out overall text and the list of items + switch (mode) { + case ITEMMODE_CHAR_INFO: + case ITEMMODE_8: + screen._windows[30].writeString(Common::String::format(X_FOR_THE_Y, + category == CATEGORY_MISC ? "\x3l" : "\x3c", + CATEGORY_NAMES[category], c->_name.c_str(), CLASS_NAMES[c->_class], + category == CATEGORY_MISC ? FMT_CHARGES : " ", + lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(), + lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(), + lines[8].c_str() + )); - if (i._material == 0) { - // No item - if (idx == 0) { - lines.push_back(NO_ITEMS_AVAILABLE); - } - } else { - ItemsMode tempMode = mode; - int skill = startingChar->_skills[MERCHANT]; - - if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8 - || mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) { - tempMode = ITEMMODE_ENCHANT; - } else if (mode == ITEMMODE_TO_GOLD) { - skill = 1; - } + case ITEMMODE_BLACKSMITH: { + // Original uses var in this block that's never set?! + const int v1 = 0; + screen._windows[30].writeString(Common::String::format(AVAILABLE_GOLD_COST, + CATEGORY_NAMES[category], + v1 ? "" : "s", party._gold, + lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(), + lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(), + lines[8].c_str() + )); + break; + } + + case ITEMMODE_2: + case ITEMMODE_RECHARGE: + case ITEMMODE_ENCHANT: + case ITEMMODE_REPAIR: + case ITEMMODE_IDENTIFY: + case ITEMMODE_TO_GOLD: + screen._windows[30].writeString(Common::String::format(X_FOR_Y, + CATEGORY_NAMES[category], startingChar->_name.c_str(), + (mode == ITEMMODE_RECHARGE || mode == ITEMMODE_ENCHANT) ? CHARGES : COST, + lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(), + lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(), + lines[8].c_str() + )); + break; - lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2, - arr[idx], idx + 1, - c->_items[category].getFullDescription(idx, arr[idx]), - calcItemCost(c, idx, tempMode, skill, category) + case ITEMMODE_3: + case ITEMMODE_5: + screen._windows[30].writeString(Common::String::format(X_FOR_Y_GOLD, + CATEGORY_NAMES[category], c->_name.c_str(), party._gold, CHARGES, + lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(), + lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(), + lines[8].c_str() )); - } break; - } default: break; } - } - while (lines.size() < INV_ITEMS_TOTAL) - lines.push_back(""); - - // Draw out overall text and the list of items - switch (mode) { - case ITEMMODE_CHAR_INFO: - case ITEMMODE_8: - screen._windows[30].writeString(Common::String::format(X_FOR_THE_Y, - category == CATEGORY_MISC ? "\x3l" : "\x3c", - CATEGORY_NAMES[category], c->_name.c_str(), CLASS_NAMES[c->_class], - category == CATEGORY_MISC ? FMT_CHARGES : " ", - lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(), - lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(), - lines[8].c_str() - )); - - case ITEMMODE_BLACKSMITH: { - // Original uses var in this block that's never set?! - const int v1 = 0; - screen._windows[30].writeString(Common::String::format(AVAILABLE_GOLD_COST, - CATEGORY_NAMES[category], - v1 ? "" : "s", party._gold, - lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(), - lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(), - lines[8].c_str() - )); - break; - } - - case ITEMMODE_2: - case ITEMMODE_RECHARGE: - case ITEMMODE_ENCHANT: - case ITEMMODE_REPAIR: - case ITEMMODE_IDENTIFY: - case ITEMMODE_TO_GOLD: - screen._windows[30].writeString(Common::String::format(X_FOR_Y, - CATEGORY_NAMES[category], startingChar->_name.c_str(), - (mode == ITEMMODE_RECHARGE || mode == ITEMMODE_ENCHANT) ? CHARGES : COST, - lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(), - lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(), - lines[8].c_str() - )); - break; - - case ITEMMODE_3: - case ITEMMODE_5: - screen._windows[30].writeString(Common::String::format(X_FOR_Y_GOLD, - CATEGORY_NAMES[category], c->_name.c_str(), party._gold, CHARGES, - lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(), - lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(), - lines[8].c_str() - )); - break; - default: - break; + // Draw the glyphs for the items + screen._windows[0].drawList(_itemsDrawList, INV_ITEMS_TOTAL); + screen._windows[0].update(); } - // Draw the glyphs for the items - screen._windows[0].drawList(_itemsDrawList, INV_ITEMS_TOTAL); - screen._windows[0].update(); + redrawFlag = REDRAW_NONE; - if (var2 != -1) { - int actionIndex = -1; + if (itemIndex != -1) { switch (mode) { case ITEMMODE_BLACKSMITH: actionIndex = 0; @@ -278,15 +286,229 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { default: break; } - - if (actionIndex >= 0) { - doItemOptions(*c, actionIndex, var2, category, mode); + } + + // If it's time to do an item action, take care of it + if (actionIndex >= 0) { + int result = doItemOptions(*c, actionIndex, itemIndex, category, mode); + if (result == 1) { + // Finish dialog with no selected character + c = nullptr; + break; + } else if (result == 2) { + // Close dialogs and finish dialog with original starting character + screen._windows[30].close(); + screen._windows[29].close(); + c = startingChar; + break; } + + // Otherwise, result and continue showing dialog + actionIndex = -1; + } + + // Wait for a selection + _buttonValue = 0; + while (!_vm->shouldQuit() && !_buttonValue) { + events.pollEventsAndWait(); + checkEvents(_vm); } + if (_vm->shouldQuit()) + return nullptr; + + // Handle escaping out of dialog + if (_buttonValue == Common::KEYCODE_ESCAPE) { + if (mode == ITEMMODE_8) + continue; + break; + } + + // Handle other selections + switch (_buttonValue) { + case Common::KEYCODE_F1: + case Common::KEYCODE_F2: + case Common::KEYCODE_F3: + case Common::KEYCODE_F4: + case Common::KEYCODE_F5: + case Common::KEYCODE_F6: + if (!varA && mode != ITEMMODE_3 && mode != ITEMMODE_ENCHANT + && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD + && party._mazeId != 0) { + _buttonValue -= Common::KEYCODE_F1; + + if (_buttonValue < (int)(_vm->_mode == MODE_InCombat ? + party._combatParty.size() : party._activeParty.size())) { + // Character number is valid + redrawFlag = REDRAW_TEXT; + Character *newChar = _vm->_mode == MODE_InCombat ? + party._combatParty[_buttonValue] : &party._activeParty[_buttonValue]; + + if (mode == ITEMMODE_BLACKSMITH) { + _oldCharacter = newChar; + startingChar = newChar; + c = &_itemsCharacter; + } else if (mode != ITEMMODE_2 && mode != ITEMMODE_REPAIR + && mode != ITEMMODE_IDENTIFY && itemIndex != -1) { + InventoryItems &destItems = newChar->_items[category]; + XeenItem &destItem = destItems[INV_ITEMS_TOTAL - 1]; + InventoryItems &srcItems = c->_items[category]; + XeenItem &srcItem = srcItems[itemIndex]; + + if (srcItem._bonusFlags & ITEMFLAG_CURSED) + ErrorScroll::show(_vm, CANNOT_REMOVE_CURSED_ITEM); + else if (destItems[INV_ITEMS_TOTAL - 1]._id) + ErrorScroll::show(_vm, Common::String::format( + CATEGORY_BACKPACK_IS_FULL[category], c->_name.c_str())); + else { + destItem = srcItem; + srcItem.clear(); + destItem._frame = 0; + + srcItems.sort(); + destItems.sort(); + } + + continue; + } + + c = newChar; + startingChar = newChar; + intf.highlightChar(_buttonValue); + } + } + break; + + case Common::KEYCODE_1: + case Common::KEYCODE_2: + case Common::KEYCODE_3: + case Common::KEYCODE_4: + case Common::KEYCODE_5: + case Common::KEYCODE_6: + case Common::KEYCODE_7: + case Common::KEYCODE_8: + case Common::KEYCODE_9: + // Select an item + if (mode == ITEMMODE_3) + break; + + _buttonValue -= Common::KEYCODE_1; + if (_buttonValue != itemIndex) { + // Check whether the new selection has an associated item + if (!c->_items[category][_buttonValue].empty()) { + itemIndex = _buttonValue; + Common::fill(&arr[0], &arr[40], 0); + arr[itemIndex] = 15; + } + + redrawFlag = REDRAW_TEXT; + } + break; + + case Common::KEYCODE_a: + // Armor category + category = CATEGORY_ARMOR; + redrawFlag = REDRAW_FULL; + break; - // TODO + case Common::KEYCODE_b: + // Buy + if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_RECHARGE && + mode != ITEMMODE_ENCHANT && mode != ITEMMODE_TO_GOLD) { + mode = ITEMMODE_BLACKSMITH; + c = &_itemsCharacter; + redrawFlag = REDRAW_FULL; + } + break; + + case Common::KEYCODE_c: + // Accessories category + category = CATEGORY_ACCESSORY; + redrawFlag = REDRAW_FULL; + break; + + case Common::KEYCODE_d: + if (mode == ITEMMODE_CHAR_INFO) + actionIndex = 3; + break; + + case Common::KEYCODE_e: + if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_ENCHANT || + mode == ITEMMODE_TO_GOLD) { + if (category != CATEGORY_MISC) { + actionIndex = mode == ITEMMODE_ENCHANT ? 4 : 0; + } + } + break; + + case Common::KEYCODE_f: + if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_RECHARGE && + mode != ITEMMODE_ENCHANT && mode != ITEMMODE_TO_GOLD) { + mode = ITEMMODE_REPAIR; + c = startingChar; + redrawFlag = REDRAW_TEXT; + } + break; + + case Common::KEYCODE_g: + if (mode == ITEMMODE_TO_GOLD) + actionIndex = 6; + break; + + case Common::KEYCODE_i: + if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_RECHARGE && + mode != ITEMMODE_ENCHANT && mode != ITEMMODE_TO_GOLD) { + mode = ITEMMODE_IDENTIFY; + c = startingChar; + redrawFlag = REDRAW_TEXT; + } + break; + + case Common::KEYCODE_n: + // Misc category + category = CATEGORY_MISC; + redrawFlag = REDRAW_TEXT; + break; + + case Common::KEYCODE_q: + if (mode == ITEMMODE_CHAR_INFO) { + Quests::show(_vm); + redrawFlag = REDRAW_TEXT; + } + break; + + case Common::KEYCODE_r: + if (mode == ITEMMODE_CHAR_INFO) + actionIndex = 1; + else if (mode == ITEMMODE_RECHARGE) + actionIndex = 5; + break; + + case Common::KEYCODE_s: + if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_RECHARGE && + mode != ITEMMODE_ENCHANT && mode != ITEMMODE_TO_GOLD) { + mode = ITEMMODE_2; + c = startingChar; + redrawFlag = REDRAW_TEXT; + } + break; + + case Common::KEYCODE_u: + if (mode == ITEMMODE_CHAR_INFO && category == CATEGORY_MISC) + actionIndex = 2; + break; + + case Common::KEYCODE_w: + // Weapons category + category = CATEGORY_WEAPON; + redrawFlag = REDRAW_TEXT; + break; + } } + intf.charIconsPrint(true); + if (updateStock) + charData2BlackData(); + return c; } @@ -378,6 +600,27 @@ void ItemsDialog::blackData2CharData() { } } +/** +* Saves the inventory from the temporary _itemsCharacter character back into the +* blacksmith storage, so changes in blacksmith inventory remain persistent +*/ +void ItemsDialog::charData2BlackData() { + Party &party = *_vm->_party; + bool isDarkCc = _vm->_files->_isDarkCc; + int slotIndex = 0; + while (party._mazeId != (int)BLACKSMITH_MAP_IDS[isDarkCc][slotIndex] && slotIndex < 4) + ++slotIndex; + if (slotIndex == 4) + slotIndex = 0; + + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + party._blacksmithWeapons[isDarkCc][idx] = _itemsCharacter._weapons[idx]; + party._blacksmithArmor[isDarkCc][idx] = _itemsCharacter._armor[idx]; + party._blacksmithAccessories[isDarkCc][idx] = _itemsCharacter._accessories[idx]; + party._blacksmithMisc[isDarkCc][idx] = _itemsCharacter._misc[idx]; + } +} + /** * Sets the equipment icon to use for each item for display */ diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h index 77b1540fbe..bc995c52f8 100644 --- a/engines/xeen/dialogs_items.h +++ b/engines/xeen/dialogs_items.h @@ -53,6 +53,8 @@ private: void blackData2CharData(); + void charData2BlackData(); + void setEquipmentIcons(); int calcItemCost(Character *c, int itemIndex, ItemsMode mode, int skillLevel, diff --git a/engines/xeen/dialogs_quests.cpp b/engines/xeen/dialogs_quests.cpp new file mode 100644 index 0000000000..27657193b8 --- /dev/null +++ b/engines/xeen/dialogs_quests.cpp @@ -0,0 +1,40 @@ +/* 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/scummsys.h" +#include "xeen/dialogs_quests.h" +#include "xeen/events.h" +#include "xeen/xeen.h" + +namespace Xeen { + +void Quests::show(XeenEngine *vm) { + Quests *dlg = new Quests(vm); + dlg->execute(); + delete dlg; +} + +void Quests::execute() { + // TODO +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_quests.h b/engines/xeen/dialogs_quests.h new file mode 100644 index 0000000000..fb39d3ace9 --- /dev/null +++ b/engines/xeen/dialogs_quests.h @@ -0,0 +1,43 @@ +/* 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 XEEN_DIALOGS_QUESTS_H +#define XEEN_DIALOGS_QUESTS_H + +#include "xeen/dialogs.h" + +namespace Xeen { + +class Quests : public ButtonContainer { +private: + XeenEngine *_vm; + + Quests(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + void execute(); +public: + static void show(XeenEngine *vm); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_QUESTS_H */ diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 6a36f91bf8..8c526b4e46 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -19,6 +19,7 @@ MODULE_OBJS := \ dialogs_input.o \ dialogs_items.o \ dialogs_query.o \ + dialogs_quests.o \ dialogs_quick_ref.o \ dialogs_spells.o \ dialogs_whowill.o \ diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 55060c8743..991c43018d 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1240,6 +1240,13 @@ const char *const PERMANENTLY_DISCARD = "\v000\t000\x03lPermanently discard %s\f const char *const BACKPACK_IS_FULL = "\v005\x03c\fd%s's backpack is full."; +const char *const CATEGORY_BACKPACK_IS_FULL[4] = { + "\v010\t000\x3""c%s's weapons backpack is full.", + "\v010\t000\x3""c%s's armor backpack is full.", + "\v010\t000\x3""c%s's accessories backpack is full.", + "\v010\t000\x3""c%s's miscellaneous backpack is full." +}; + const char *const BUY_X_FOR_Y_GOLD = "\x3l\v000\t000\fdBuy %s\fd for %lu gold?"; const char *const SELL_X_FOR_Y_GOLD = "\x3l\v000\t000\fdSell %s\fd for %lu gold?"; diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index cab2af7c43..4c79a1ea27 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -443,6 +443,8 @@ extern const char *const PERMANENTLY_DISCARD; extern const char *const BACKPACK_IS_FULL; +extern const char *const CATEGORY_BACKPACK_IS_FULL[4]; + extern const char *const BUY_X_FOR_Y_GOLD; extern const char *const SELL_X_FOR_Y_GOLD; -- cgit v1.2.3 From 90db7872f14c67f990c74f6b2d971f479dc87941 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Feb 2015 18:02:03 -0500 Subject: XEEN: Implement Quests dialog --- engines/xeen/dialogs_quests.cpp | 210 +++++++++++++++++++++++++++++++++++++++- engines/xeen/dialogs_quests.h | 7 ++ engines/xeen/interface.cpp | 6 ++ engines/xeen/party.h | 4 +- engines/xeen/resources.cpp | 135 ++++++++++++++++++++++++++ engines/xeen/resources.h | 12 +++ 6 files changed, 372 insertions(+), 2 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_quests.cpp b/engines/xeen/dialogs_quests.cpp index 27657193b8..17255946bc 100644 --- a/engines/xeen/dialogs_quests.cpp +++ b/engines/xeen/dialogs_quests.cpp @@ -23,10 +23,13 @@ #include "common/scummsys.h" #include "xeen/dialogs_quests.h" #include "xeen/events.h" +#include "xeen/party.h" #include "xeen/xeen.h" namespace Xeen { +#define MAX_DIALOG_LINES 128 + void Quests::show(XeenEngine *vm) { Quests *dlg = new Quests(vm); dlg->execute(); @@ -34,7 +37,212 @@ void Quests::show(XeenEngine *vm) { } void Quests::execute() { - // TODO + EventsManager &events = *_vm->_events; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + bool isDarkCc = _vm->_files->_isDarkCc; + int count = 0; + bool headerShown = false; + int topRow = 0; + + addButtons(); + loadQuestNotes(); + + enum { QUEST_ITEMS, CURRENT_QUESTS, AUTO_NOTES } mode = QUEST_ITEMS; + bool windowFlag; + if (screen._windows[29]._enabled) { + windowFlag = false; + } else { + screen._windows[29].open(); + screen._windows[30].open(); + windowFlag = true; + } + + screen._windows[29].writeString(QUESTS_DIALOG_TEXT); + drawButtons(&screen); + + while (!_vm->shouldQuit()) { + Common::String lines[MAX_DIALOG_LINES]; + + switch (mode) { + case QUEST_ITEMS: + for (int idx = 0; idx < TOTAL_QUEST_ITEMS; ++idx) + lines[idx] = "\b \b*"; + + count = 0; + headerShown = false; + for (int idx = 0; idx < TOTAL_QUEST_ITEMS; ++idx) { + if (party._questItems[idx]) { + if (!count && !headerShown && idx < 35) { + lines[count++] = CLOUDS_OF_XEEN_LINE; + } + if (idx >= 35 && !headerShown) { + lines[count++] = DARKSIDE_OF_XEEN_LINE; + headerShown = true; + } + + switch (idx) { + case 17: + case 26: + case 79: + case 80: + case 81: + case 82: + case 83: + case 84: + lines[count++] = Common::String::format("%d %s%c", + party._questItems[idx], QUEST_ITEM_NAMES[idx], + party._questItems[idx] == 1 ? ' ' : 's'); + break; + default: + lines[count++] = QUEST_ITEM_NAMES[idx]; + break; + } + } + } + + if (count == 0) { + screen._windows[30].writeString(NO_QUEST_ITEMS); + } else { + screen._windows[30].writeString(Common::String::format(QUEST_ITEMS_DATA, + lines[topRow].c_str(), lines[topRow + 1].c_str(), + lines[topRow + 2].c_str(), lines[topRow + 3].c_str(), + lines[topRow + 4].c_str(), lines[topRow + 5].c_str(), + lines[topRow + 6].c_str(), lines[topRow + 7].c_str(), + lines[topRow + 8].c_str() + )); + } + break; + + case CURRENT_QUESTS: + for (int idx = 0; idx < TOTAL_QUEST_ITEMS; ++idx) + lines[idx] = ""; + + count = 0; + headerShown = false; + for (int idx = 0; idx < TOTAL_QUEST_FLAGS; ++idx) { + if (party._quests[idx]) { + if (!count && !headerShown && idx < 29) { + lines[count++] = CLOUDS_OF_XEEN_LINE; + } + if (idx > 28 && !headerShown) { + lines[count++] = DARKSIDE_OF_XEEN_LINE; + headerShown = true; + } + + lines[count++] = _questNotes[idx]; + } + } + + if (count == 0) + lines[1] = NO_CURRENT_QUESTS; + + screen._windows[30].writeString(Common::String::format(CURRENT_QUESTS_DATA, + lines[topRow].c_str(), lines[topRow + 1].c_str(), lines[topRow + 2].c_str())); + break; + + case AUTO_NOTES: + for (int idx = 0; idx < MAX_DIALOG_LINES; ++idx) + lines[idx] = ""; + + count = 0; + headerShown = false; + for (int idx = 0; idx < MAX_DIALOG_LINES; ++idx) { + if (party._worldFlags[idx]) { + if (!count && !headerShown && idx < 72) { + lines[count++] = CLOUDS_OF_XEEN_LINE; + } + if (idx >= 72 && !headerShown) { + lines[count++] = DARKSIDE_OF_XEEN_LINE; + headerShown = true; + } + + lines[count++] = _questNotes[idx + 56]; + } + } + + if (count == 0) + lines[1] = NO_AUTO_NOTES; + + screen._windows[30].writeString(Common::String::format(AUTO_NOTES_DATA, + lines[topRow].c_str(), lines[topRow + 1].c_str(), + lines[topRow + 2].c_str(), lines[topRow + 3].c_str(), + lines[topRow + 4].c_str(), lines[topRow + 5].c_str(), + lines[topRow + 6].c_str(), lines[topRow + 7].c_str(), + lines[topRow + 8].c_str() + )); + break; + } + + screen._windows[30].writeString("\v000\t000"); + screen._windows[24].update(); + + // Key handling + _buttonValue = 0; + while (!_vm->shouldQuit() && !_buttonValue) { + events.pollEventsAndWait(); + checkEvents(_vm); + } + + if (_buttonValue == Common::KEYCODE_ESCAPE) + break; + + switch (_buttonValue) { + case Common::KEYCODE_a: + mode = AUTO_NOTES; + break; + case Common::KEYCODE_i: + mode = QUEST_ITEMS; + break; + case Common::KEYCODE_q: + mode = CURRENT_QUESTS; + break; + case Common::KEYCODE_HOME: + topRow = 0; + break; + case Common::KEYCODE_END: + topRow = count - 1; + break; + case Common::KEYCODE_PAGEUP: + topRow = MAX(topRow - 3, 0); + break; + case Common::KEYCODE_PAGEDOWN: + topRow = CLIP(topRow + 3, 0, count - 1); + break; + case Common::KEYCODE_UP: + case Common::KEYCODE_KP8: + topRow = MAX(topRow - 1, 0); + break; + case Common::KEYCODE_DOWN: + case Common::KEYCODE_KP2: + topRow = CLIP(topRow + 1, 0, count - 1); + break; + default: + break; + } + } + + if (windowFlag) { + screen._windows[30].close(); + screen._windows[29].close(); + } +} + +void Quests::addButtons() { + _iconSprites.load("quest.icn"); + addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_i, &_iconSprites); + addButton(Common::Rect(80, 109, 104, 129), Common::KEYCODE_q, &_iconSprites); + addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_a, &_iconSprites); + addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_i, &_iconSprites); + addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_UP, &_iconSprites); + addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_DOWN, &_iconSprites); +} + +void Quests::loadQuestNotes() { + File f("qnotes.bin"); + while (f.pos() < f.size()) + _questNotes.push_back(f.readString()); + f.close(); } } // End of namespace Xeen diff --git a/engines/xeen/dialogs_quests.h b/engines/xeen/dialogs_quests.h index fb39d3ace9..234accded6 100644 --- a/engines/xeen/dialogs_quests.h +++ b/engines/xeen/dialogs_quests.h @@ -23,6 +23,7 @@ #ifndef XEEN_DIALOGS_QUESTS_H #define XEEN_DIALOGS_QUESTS_H +#include "common/str-array.h" #include "xeen/dialogs.h" namespace Xeen { @@ -30,10 +31,16 @@ namespace Xeen { class Quests : public ButtonContainer { private: XeenEngine *_vm; + SpriteResource _iconSprites; + Common::StringArray _questNotes; Quests(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} void execute(); + + void addButtons(); + + void loadQuestNotes(); public: static void show(XeenEngine *vm); }; diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 520cad5c05..34c7b548ff 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -25,6 +25,7 @@ #include "xeen/dialogs_error.h" #include "xeen/dialogs_automap.h" #include "xeen/dialogs_info.h" +#include "xeen/dialogs_quests.h" #include "xeen/dialogs_quick_ref.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -710,6 +711,11 @@ void Interface::perform() { QuickReferenceDialog::show(_vm); break; + case Common::KEYCODE_v: + // Show the quests dialog + Quests::show(_vm); + break; + default: break; } diff --git a/engines/xeen/party.h b/engines/xeen/party.h index ec7a8b99e1..b1ca067df4 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -45,6 +45,8 @@ enum Difficulty { ADVENTURER = 0, WARRIOR = 1 }; #define XEEN_TOTAL_CHARACTERS 24 #define MAX_ACTIVE_PARTY 6 #define TOTAL_STATS 7 +#define TOTAL_QUEST_ITEMS 85 +#define TOTAL_QUEST_FLAGS 56 class Roster: public Common::Array<Character> { public: @@ -107,7 +109,7 @@ public: bool _gameFlags[512]; bool _worldFlags[128]; bool _quests[64]; - int _questItems[85]; + int _questItems[TOTAL_QUEST_ITEMS]; bool _characterFlags[30][24]; public: // Other party related runtime data diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 991c43018d..eeea54c81b 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1144,6 +1144,94 @@ const char *const EFFECTIVENESS_NAMES[7] = { nullptr, "Dragons", "Undead", "Golems", "Bugs", "Monsters", "Beasts" }; +const char *const QUEST_ITEM_NAMES[85] = { + "Deed to New Castle", + "Crystal Key to Witch Tower", + "Skeleton Key to Darzog's Tower", + "Enchanted Key to Tower of High Magic", + "Jeweled Amulet of the Northern Sphinx", + "Stone of a Thousand Terrors", + "Golem Stone of Admittance", + "Yak Stone of Opening", + "Xeen's Scepter of Temporal Distortion", + "Alacorn of Falista", + "Elixir of Restoration", + "Wand of Faery Magic", + "Princess Roxanne's Tiara", + "Holy Book of Elvenkind", + "Scarab of Imaging", + "Crystals of Piezoelectricity", + "Scroll of Insight", + "Phirna Root", + "Orothin's Bone Whistle", + "Barok's Magic Pendant", + "Ligono's Missing Skull", + "Last Flower of Summer", + "Last Raindrop of Spring", + "Last Snowflake of Winter", + "Last Leaf of Autumn", + "Ever Hot Lava Rock", + "King's Mega Credit", + "Excavation Permit", + "Cupie Doll", + "Might Doll", + "Speed Doll", + "Endurance Doll", + "Accuracy Doll", + "Luck Doll", + "Widget", + "Pass to Castleview", + "Pass to Sandcaster", + "Pass to Lakeside", + "Pass to Necropolis", + "Pass to Olympus", + "Key to Great Western Tower", + "Key to Great Southern Tower", + "Key to Great Eastern Tower", + "Key to Great Northern Tower", + "Key to Ellinger's Tower", + "Key to Dragon Tower", + "Key to Darkstone Tower", + "Key to Temple of Bark", + "Key to Dungeon of Lost Souls", + "Key to Ancient Pyramid", + "Key to Dungeon of Death", + "Amulet of the Southern Sphinx", + "Dragon Pharoah's Orb", + "Cube of Power", + "Chime of Opening", + "Gold ID Card", + "Silver ID Card", + "Vulture Repellant", + "Bridle", + "Enchanted Bridle", + "Treasure Map (Goto E1 x1, y11)", + nullptr, + "Fake Map", + "Onyx Necklace", + "Dragon Egg", + "Tribble", + "Golden Pegasus Statuette", + "Golden Dragon Statuette", + "Golden Griffin Statuette", + "Chalice of Protection", + "Jewel of Ages", + "Songbird of Serenity", + "Sandro's Heart", + "Ector's Ring", + "Vespar's Emerald Handle", + "Queen Kalindra's Crown", + "Caleb's Magnifying Glass", + "Soul Box", + "Soul Box with Corak inside", + "Ruby Rock", + "Emerald Rock", + "Sapphire Rock", + "Diamond Rock", + "Monga Melon", + "Energy Disk" +}; + const int WEAPON_BASE_COSTS[35] = { 0, 50, 15, 100, 80, 40, 60, 1, 10, 150, 30, 60, 8, 50, 100, 15, 30, 15, 200, 80, 250, 150, 400, 100, 40, 120, @@ -1288,4 +1376,51 @@ const char *const ELEMENTAL_XY_DAMAGE = "%+d %s Damage"; const char *const ATTR_XY_BONUS = "%+d %s"; const char *const EFFECTIVE_AGAINST = "x3 vs %s"; +const char *const QUESTS_DIALOG_TEXT = + "\r2\x2""c\v021\t017\f37I\fdtems\t085\f37Q\fduests\t153" + "\f37A\fduto Notes\t221\f37U\fdp\t255\f37D\fdown\t289Exit"; + +const char *const CLOUDS_OF_XEEN_LINE = "\b \b*-- \f04Clouds of Xeen\fd --"; +const char *const DARKSIDE_OF_XEEN_LINE = "\b \b*-- \f04Darkside of Xeen\fd --"; + +const char *const NO_QUEST_ITEMS = + "\rd\x3""c\v000 000Quest Items\x3l\x2\n" + "\n" + "\x3""cNo Quest Items"; +const char *const NO_CURRENT_QUESTS = + "\x3""c\v000\t000\n" + "\n" + "No Current Quests"; +const char *const NO_AUTO_NOTES = "\x3""cNo Auto Notes"; + +const char *const QUEST_ITEMS_DATA = + "\r\x1\fd\x3""c\v000\t000Quest Items\x3l\x2\n" + "\f04 * \fd%s\n" + "\f04 * \fd%s\n" + "\f04 * \fd%s\n" + "\f04 * \fd%s\n" + "\f04 * \fd%s\n" + "\f04 * \fd%s\n" + "\f04 * \fd%s\n" + "\f04 * \fd%s\n" + "\f04 * \fd%s"; +const char *const CURRENT_QUESTS_DATA = + "\r\x1\fd\x3""c\t000\v000Current Quests\x3l\x2\n" + "%s\n" + "\n" + "%s\n" + "\n" + "%s"; +const char *const AUTO_NOTES_DATA = + "\r\x1\fd\x3""c\t000\v000Auto Notes\x3l\x2\n" + "%s\x3l\n" + "%s\x3l\n" + "%s\x3l\n" + "%s\x3l\n" + "%s\x3l\n" + "%s\x3l\n" + "%s\x3l\n" + "%s\x3l\n" + "%s\x3l"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 4c79a1ea27..9c0136c06f 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -387,6 +387,7 @@ extern const char *const MISC_NAMES[22]; extern const char *const ELEMENTAL_NAMES[6]; extern const char *const ATTRIBUTE_NAMES[10]; extern const char *const EFFECTIVENESS_NAMES[7]; +extern const char *const QUEST_ITEM_NAMES[85]; extern const int WEAPON_BASE_COSTS[35]; extern const int ARMOR_BASE_COSTS[25]; @@ -474,6 +475,17 @@ extern const char *const ELEMENTAL_XY_DAMAGE; extern const char *const ATTR_XY_BONUS; extern const char *const EFFECTIVE_AGAINST; +extern const char *const QUESTS_DIALOG_TEXT; +extern const char *const CLOUDS_OF_XEEN_LINE; +extern const char *const DARKSIDE_OF_XEEN_LINE; + +extern const char *const NO_QUEST_ITEMS; +extern const char *const NO_CURRENT_QUESTS; +extern const char *const NO_AUTO_NOTES; +extern const char *const QUEST_ITEMS_DATA; +extern const char *const CURRENT_QUESTS_DATA; +extern const char *const AUTO_NOTES_DATA; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From 528fce5ac4ffec769a0f60472a6d947320b3301b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Feb 2015 18:14:43 -0500 Subject: XEEN: Fix headers and key handling in Quests dialog --- engines/xeen/dialogs_quests.cpp | 6 +++--- engines/xeen/resources.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_quests.cpp b/engines/xeen/dialogs_quests.cpp index 17255946bc..146415b6c2 100644 --- a/engines/xeen/dialogs_quests.cpp +++ b/engines/xeen/dialogs_quests.cpp @@ -233,9 +233,9 @@ void Quests::addButtons() { addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_i, &_iconSprites); addButton(Common::Rect(80, 109, 104, 129), Common::KEYCODE_q, &_iconSprites); addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_a, &_iconSprites); - addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_i, &_iconSprites); - addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_UP, &_iconSprites); - addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_DOWN, &_iconSprites); + addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_UP, &_iconSprites); + addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_DOWN, &_iconSprites); + addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites); } void Quests::loadQuestNotes() { diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index eeea54c81b..5a50e076ca 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1377,14 +1377,14 @@ const char *const ATTR_XY_BONUS = "%+d %s"; const char *const EFFECTIVE_AGAINST = "x3 vs %s"; const char *const QUESTS_DIALOG_TEXT = - "\r2\x2""c\v021\t017\f37I\fdtems\t085\f37Q\fduests\t153" - "\f37A\fduto Notes\t221\f37U\fdp\t255\f37D\fdown\t289Exit"; - + "\r\x2\x3""c\v021\t017\f37I\fdtems\t085\f37Q\fduests\t153" + "\f37A\fduto Notes 221\f37U\fdp\t255\f37D\fdown" + "\t289Exit"; const char *const CLOUDS_OF_XEEN_LINE = "\b \b*-- \f04Clouds of Xeen\fd --"; const char *const DARKSIDE_OF_XEEN_LINE = "\b \b*-- \f04Darkside of Xeen\fd --"; const char *const NO_QUEST_ITEMS = - "\rd\x3""c\v000 000Quest Items\x3l\x2\n" + "\r\x3""c\v000 000Quest Items\x3l\x2\n" "\n" "\x3""cNo Quest Items"; const char *const NO_CURRENT_QUESTS = -- cgit v1.2.3 From c313113f6b72524c1bdc41fd30c2bdc4182de3a4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Feb 2015 18:32:37 -0500 Subject: XEEN: Fix for switching modes and loading auto notes in Quests dialog --- engines/xeen/dialogs_quests.cpp | 10 ++++++++-- engines/xeen/resources.cpp | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_quests.cpp b/engines/xeen/dialogs_quests.cpp index 146415b6c2..284e15781b 100644 --- a/engines/xeen/dialogs_quests.cpp +++ b/engines/xeen/dialogs_quests.cpp @@ -40,7 +40,7 @@ void Quests::execute() { EventsManager &events = *_vm->_events; Party &party = *_vm->_party; Screen &screen = *_vm->_screen; - bool isDarkCc = _vm->_files->_isDarkCc; + Mode oldMode = _vm->_mode; int count = 0; bool headerShown = false; int topRow = 0; @@ -190,12 +190,15 @@ void Quests::execute() { switch (_buttonValue) { case Common::KEYCODE_a: mode = AUTO_NOTES; + topRow = 0; break; case Common::KEYCODE_i: mode = QUEST_ITEMS; + topRow = 0; break; case Common::KEYCODE_q: mode = CURRENT_QUESTS; + topRow = 0; break; case Common::KEYCODE_HOME: topRow = 0; @@ -226,10 +229,13 @@ void Quests::execute() { screen._windows[30].close(); screen._windows[29].close(); } + _vm->_mode = oldMode; } void Quests::addButtons() { _iconSprites.load("quest.icn"); + + addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_i, &_iconSprites); addButton(Common::Rect(80, 109, 104, 129), Common::KEYCODE_q, &_iconSprites); addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_a, &_iconSprites); @@ -239,7 +245,7 @@ void Quests::addButtons() { } void Quests::loadQuestNotes() { - File f("qnotes.bin"); + File f("qnotes.bin", *_vm->_files->_sideArchives[_vm->getGameID() == GType_Clouds ? 0 : 1]); while (f.pos() < f.size()) _questNotes.push_back(f.readString()); f.close(); diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 5a50e076ca..204e727326 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1206,7 +1206,7 @@ const char *const QUEST_ITEM_NAMES[85] = { "Bridle", "Enchanted Bridle", "Treasure Map (Goto E1 x1, y11)", - nullptr, + "", "Fake Map", "Onyx Necklace", "Dragon Egg", -- cgit v1.2.3 From 996ce240833477855f5787a9f3501e8dc8ba8022 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Feb 2015 18:43:05 -0500 Subject: XEEN: Fix writeString to constrain text to window --- engines/xeen/font.cpp | 18 ++++++++++++------ engines/xeen/font.h | 4 ++-- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp index aca747e776..53308ae248 100644 --- a/engines/xeen/font.cpp +++ b/engines/xeen/font.cpp @@ -60,7 +60,7 @@ void FontSurface::writeSymbol(int symbolId) { /** * Write a string to the surface * @param s String to display - * @param bounds Window bounds to display string within + * @param clipRect Window bounds to display string within * @returns Any string remainder that couldn't be displayed * @remarks Note that bounds is just used for wrapping purposes. Unless * justification is set, the message will be written at _writePos @@ -183,7 +183,7 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R continue; } else if (c == 6) { // Non-breakable space - writeChar(' '); + writeChar(' ', bounds); } else if (c == 7) { // Set text background color int bgColor = fontAtoi(); @@ -210,7 +210,7 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R Common::copy(&_textColors[0], &_textColors[4], &oldColor[0]); _textColors[1] = _textColors[2] = _textColors[3] = _bgColor; - writeChar(c); + writeChar(c, bounds); Common::copy(&oldColor[0], &oldColor[4], &_textColors[0]); _writePos.x = oldX; @@ -239,7 +239,7 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R break; } else { // Standard character - write it out - writeChar(c); + writeChar(c, bounds); } } @@ -340,7 +340,7 @@ void FontSurface::setTextColor(int idx) { /** * Wrie a character to the surface */ -void FontSurface::writeChar(char c) { +void FontSurface::writeChar(char c, const Common::Rect &clipRect) { // Get y position, handling kerning int y = _writePos.y; if (c == 'g' || c == 'p' || c == 'q' || c == 'y') @@ -354,11 +354,17 @@ void FontSurface::writeChar(char c) { uint16 lineData = READ_LE_UINT16(srcP); srcP += 2; byte *destP = (byte *)getBasePtr(_writePos.x, y); + // Ignore line if it's outside the clipping rect + if (y < clipRect.top || y >= clipRect.bottom) + continue; + const byte *lineStart = (const byte *)getBasePtr(clipRect.left, y); + const byte *lineEnd = (const byte *)getBasePtr(clipRect.right, y); + for (int xp = 0; xp < FONT_WIDTH; ++xp, ++destP) { int colIndex = lineData & 3; lineData >>= 2; - if (colIndex) + if (colIndex && destP >= lineStart && destP < lineEnd) *destP = _textColors[colIndex]; } } diff --git a/engines/xeen/font.h b/engines/xeen/font.h index 6b362d7bf5..db61e3ea59 100644 --- a/engines/xeen/font.h +++ b/engines/xeen/font.h @@ -48,7 +48,7 @@ private: void setTextColor(int idx); - void writeChar(char c); + void writeChar(char c, const Common::Rect &clipRect); public: const byte *_fontData; Common::Point _writePos; @@ -63,7 +63,7 @@ public: void writeSymbol(int symbolId); - Common::String writeString(const Common::String &s, const Common::Rect &bounds); + Common::String writeString(const Common::String &s, const Common::Rect &clipRect); }; } // End of namespace Xeen -- cgit v1.2.3 From 54ae7eb22a33ec6bb506d5458a0f7c1bbc6945fd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Feb 2015 19:00:21 -0500 Subject: XEEN: Fix incorrect variable usage in makeItem --- engines/xeen/character.cpp | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index cde244b051..9d67567501 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -1693,32 +1693,23 @@ int Character::makeItem(int p1, int itemIndex, int p3) { rval = vm->getRandomNumber(1, 100); if (rval <= 15) { mult = 0; - } - else if (rval <= 25) { + } else if (rval <= 25) { mult = 1; - } - else if (rval <= 35) { + } else if (rval <= 35) { mult = 2; - } - else if (mult <= 50) { + } else if (rval <= 50) { mult = 3; - } - else if (mult <= 65) { + } else if (rval <= 65) { mult = 4; - } - else if (mult <= 80) { + } else if (rval <= 80) { mult = 5; - } - else if (mult <= 85) { + } else if (rval <= 85) { mult = 6; - } - else if (mult <= 90) { + } else if (rval <= 90) { mult = 7; - } - else if (mult <= 95) { + } else if (rval <= 95) { mult = 8; - } - else { + } else { mult = 9; } -- cgit v1.2.3 From 65ecc9b72138f2dcef0ccf3765363559649b77a2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Feb 2015 19:08:44 -0500 Subject: XEEN: Another fix for makeItem variable usage --- engines/xeen/character.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index 9d67567501..4e4a4da697 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -1718,7 +1718,7 @@ int Character::makeItem(int p1, int itemIndex, int p3) { break; case 3: - rval = p1 == 7 || vm->getRandomNumber(1, 100) > 70; + mult = p1 == 7 || vm->getRandomNumber(1, 100) > 70 ? 1 : 0; v16 = vm->getRandomNumber(MAKE_ITEM_ARR4[mult][p1][0], MAKE_ITEM_ARR4[mult][p1][1]); break; -- cgit v1.2.3 From d6e760552e785e466b5d2088570baa182d42ccd0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Feb 2015 21:17:31 -0500 Subject: XEEN: Implemented resting --- engines/xeen/character.h | 2 +- engines/xeen/dialogs_char_info.cpp | 12 ++-- engines/xeen/dialogs_error.cpp | 2 +- engines/xeen/dialogs_items.cpp | 6 +- engines/xeen/dialogs_spells.cpp | 2 +- engines/xeen/interface.cpp | 139 ++++++++++++++++++++++++++++++++++++- engines/xeen/interface.h | 2 + engines/xeen/interface_map.cpp | 2 +- engines/xeen/map.cpp | 2 +- engines/xeen/map.h | 9 ++- engines/xeen/party.cpp | 18 ++++- engines/xeen/party.h | 3 + engines/xeen/resources.cpp | 9 +++ engines/xeen/resources.h | 6 ++ engines/xeen/spells.cpp | 2 +- engines/xeen/xeen.h | 5 +- 16 files changed, 200 insertions(+), 21 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.h b/engines/xeen/character.h index af9e331fb5..c9a787cbc5 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -67,7 +67,7 @@ enum Skill { enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, - DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, + DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, ASLEEP = 8, DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11, UNCONSCIOUS = 12, DEAD = 13, STONED = 14, ERADICATED = 15, NO_CONDITION = 16 diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp index 0c71bfb0be..36ca5bdd4c 100644 --- a/engines/xeen/dialogs_char_info.cpp +++ b/engines/xeen/dialogs_char_info.cpp @@ -47,7 +47,7 @@ void CharacterInfo::execute(int charIndex) { loadDrawStructs(); addButtons(); - Character *c = (oldMode != MODE_InCombat) ? &party._activeParty[charIndex] : party._combatParty[charIndex]; + Character *c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : party._combatParty[charIndex]; intf.highlightChar(charIndex); Window &w = screen._windows[24]; w.open(); @@ -86,9 +86,9 @@ void CharacterInfo::execute(int charIndex) { case Common::KEYCODE_F5: case Common::KEYCODE_F6: _buttonValue -= Common::KEYCODE_F1; - if (_buttonValue < (int)(oldMode == MODE_InCombat ? party._combatParty.size() : party._activeParty.size())) { + if (_buttonValue < (int)(oldMode == MODE_COMBAT ? party._combatParty.size() : party._activeParty.size())) { charIndex = _buttonValue; - c = (oldMode != MODE_InCombat) ? &party._activeParty[charIndex] : party._combatParty[charIndex]; + c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : party._combatParty[charIndex]; } else { _vm->_mode = MODE_CHARACTER_INFO; } @@ -166,14 +166,14 @@ void CharacterInfo::execute(int charIndex) { w.update(); bool result = expandStat(_cursorCell, *c); - _vm->_mode = MODE_InCombat; + _vm->_mode = MODE_COMBAT; if (result) redrawFlag = true; break; } case Common::KEYCODE_e: - if (oldMode == MODE_InCombat) { + if (oldMode == MODE_COMBAT) { ErrorScroll::show(_vm, EXCHANGING_IN_COMBAT, WT_FREEZE_WAIT); } else { _vm->_mode = oldMode; @@ -185,7 +185,7 @@ void CharacterInfo::execute(int charIndex) { case Common::KEYCODE_i: _vm->_mode = oldMode; - _vm->_combat->_itemFlag = _vm->_mode == MODE_InCombat; + _vm->_combat->_itemFlag = _vm->_mode == MODE_COMBAT; c = ItemsDialog::show(_vm, c, ITEMMODE_CHAR_INFO); if (!c) { diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp index 598af1ede7..4fe39db3b3 100644 --- a/engines/xeen/dialogs_error.cpp +++ b/engines/xeen/dialogs_error.cpp @@ -76,7 +76,7 @@ void ErrorDialog::execute(const Common::String &msg, ErrorWaitType waitType) { /*------------------------------------------------------------------------*/ void ErrorScroll::show(XeenEngine *vm, const Common::String &msg, ErrorWaitType waitType) { - Common::String s = Common::String::format("\x03c\v010\t000%s", msg.c_str()); + Common::String s = Common::String::format("\x3""c\v010\t000%s", msg.c_str()); ErrorDialog::show(vm, s, waitType); } diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index 83e0dd23a0..002a8fb946 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -336,11 +336,11 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { && party._mazeId != 0) { _buttonValue -= Common::KEYCODE_F1; - if (_buttonValue < (int)(_vm->_mode == MODE_InCombat ? + if (_buttonValue < (int)(_vm->_mode == MODE_COMBAT ? party._combatParty.size() : party._activeParty.size())) { // Character number is valid redrawFlag = REDRAW_TEXT; - Character *newChar = _vm->_mode == MODE_InCombat ? + Character *newChar = _vm->_mode == MODE_COMBAT ? party._combatParty[_buttonValue] : &party._activeParty[_buttonValue]; if (mode == ITEMMODE_BLACKSMITH) { @@ -867,7 +867,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite Condition condition = c.worstCondition(); switch (condition) { - case SLEEP: + case ASLEEP: case PARALYZED: case UNCONSCIOUS: case DEAD: diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 4f86707554..dc05be611d 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -109,7 +109,7 @@ Character *SpellsScroll::execute(Character *c, int v2) { switch (_buttonValue) { case Common::KEYCODE_F1: case Common::KEYCODE_F6: - if (_vm->_mode != MODE_InCombat) { + if (_vm->_mode != MODE_COMBAT) { _buttonValue -= Common::KEYCODE_F1; if (_buttonValue < party._partyCount) { c = &party._activeParty[_buttonValue]; diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 34c7b548ff..c31ff844d9 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -25,6 +25,7 @@ #include "xeen/dialogs_error.h" #include "xeen/dialogs_automap.h" #include "xeen/dialogs_info.h" +#include "xeen/dialogs_query.h" #include "xeen/dialogs_quests.h" #include "xeen/dialogs_quick_ref.h" #include "xeen/resources.h" @@ -334,7 +335,7 @@ void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool void Interface::charIconsPrint(bool updateFlag) { Screen &screen = *_vm->_screen; - bool stateFlag = _vm->_mode == MODE_InCombat; + bool stateFlag = _vm->_mode == MODE_COMBAT; _restoreSprites.draw(screen, 0, Common::Point(8, 149)); // Handle drawing the party faces @@ -711,6 +712,11 @@ void Interface::perform() { QuickReferenceDialog::show(_vm); break; + case Common::KEYCODE_r: + // Rest + rest(); + break; + case Common::KEYCODE_v: // Show the quests dialog Quests::show(_vm); @@ -949,4 +955,135 @@ bool Interface::checkMoveDirection(int key) { return true; } +void Interface::rest() { + EventsManager &events = *_vm->_events; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + + map.cellFlagLookup(party._mazePosition); + + if ((map._currentCantRest || (map.mazeData()._mazeFlags & RESTRICTION_REST)) + && _vm->_mode != MODE_12) { + ErrorScroll::show(_vm, TOO_DANGEROUS_TO_REST, WT_NONFREEZED_WAIT); + } else { + // Check whether any character is in danger of dying + bool dangerFlag = false; + for (uint charIdx = 0; charIdx < party._activeParty.size(); ++charIdx) { + for (int attrib = MIGHT; attrib <= LUCK; ++attrib) { + if (party._activeParty[charIdx].getStat((Attribute)attrib) < 1) + dangerFlag = true; + } + } + + if (dangerFlag) { + if (!Confirm::show(_vm, SOME_CHARS_MAY_DIE)) + return; + } + + // Mark all the players as being asleep + for (uint charIdx = 0; charIdx < party._activeParty.size(); ++charIdx) { + party._activeParty[charIdx]._conditions[ASLEEP] = 1; + } + charIconsPrint(true); + + Mode oldMode = _vm->_mode; + _vm->_mode = MODE_SLEEPING; + + if (oldMode == MODE_12) { + party.changeTime(8 * 60); + } else { + for (int idx = 0; idx < 10; ++idx) { + chargeStep(); + draw3d(true); + + if (_vm->_mode == MODE_1) { + _vm->_mode = oldMode; + return; + } + } + + party.changeTime(map._isOutdoors ? 380 : 470); + } + + if (_vm->getRandomNumber(1, 20) == 1) { + // Show dream + screen.saveBackground(); + screen.fadeOut(4); + events.hideCursor(); + + screen.loadBackground("scene1.raw"); + screen._windows[0].update(); + screen.fadeIn(4); + + events.updateGameCounter(); + while (!_vm->shouldQuit() && events.timeElapsed() < 7) + events.pollEventsAndWait(); + + File f("dreams2.voc"); + sound.playSample(&f, 1); + while (!_vm->shouldQuit() && sound.playSample(1, 0)) + events.pollEventsAndWait(); + f.close(); + + f.openFile("laff1.voc"); + sound.playSample(&f, 1); + while (!_vm->shouldQuit() && sound.playSample(1, 0)) + events.pollEventsAndWait(); + f.close(); + + events.updateGameCounter(); + while (!_vm->shouldQuit() && events.timeElapsed() < 7) + events.pollEventsAndWait(); + + screen.fadeOut(4); + events.setCursor(0); + screen.restoreBackground(); + screen._windows[0].update(); + + screen.fadeIn(4); + } + + party.resetTemps(); + + // Wake up the party + bool starving = false; + int foodConsumed = 0; + for (uint charIdx = 0; charIdx < party._activeParty.size(); ++charIdx) { + Character &c = party._activeParty[charIdx]; + c._conditions[ASLEEP] = 0; + + if (party._food == 0) { + starving = true; + } else { + party._rested = true; + Condition condition = c.worstCondition(); + + if (condition < DEAD || condition > ERADICATED) { + --party._food; + ++foodConsumed; + party._heroism = 0; + party._holyBonus = 0; + party._powerShield = 0; + party._blessed = 0; + c._conditions[UNCONSCIOUS] = 0; + c._currentHp = c.getMaxHP(); + c._currentSp = c.getMaxSP(); + } + } + } + + charIconsPrint(true); + _vm->_mode = oldMode; + doStepCode(); + draw3d(true); + + ErrorScroll::show(_vm, Common::String::format(REST_COMPLETE, + starving ? PARTY_IS_STARVING : HIT_SPELL_POINTS_RESTORED, + foodConsumed)); + party.checkPartyDead(); + } +} + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 103b8b6607..cecc5c3a58 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -104,6 +104,8 @@ public: void unhighlightChar(); void perform(); + + void rest(); }; } // End of namespace Xeen diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index c8683a7e50..42c5ff4e07 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -426,7 +426,7 @@ void InterfaceMap::draw3d(bool updateFlag) { _flipUIFrame = (_flipUIFrame + 1) % 4; if (_flipUIFrame == 0) _flipWater = !_flipWater; - if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_InCombat) && + if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_COMBAT) && !_flag1 && _vm->_moveMonsters) { if (--_tillMove == 0) moveMonsters(); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 51e87ef97e..dc58c2db6d 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1369,7 +1369,7 @@ void Map::cellFlagLookup(const Common::Point &pt) { // Get the cell flags const MazeCell &cell = _mazeData[_mazeDataIndex]._cells[pos.y][pos.x]; _currentIsGrate = cell._flags & OUTFLAG_GRATE; - _currentCantRest = cell._flags & FLAG_WATER; + _currentCantRest = cell._flags & RESTRICTION_REST; _currentIsDrain = cell._flags & OUTFLAG_DRAIN; _currentIsEvent = cell._flags & FLAG_AUTOEXECUTE_EVENT; _currentSky = (cell._flags & OUTFLAG_OBJECT_EXISTS) ? 1 : 0; diff --git a/engines/xeen/map.h b/engines/xeen/map.h index abc36411ee..806b4084c7 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -137,8 +137,13 @@ public: enum MazeFlags { OUTFLAG_GRATE = 0x80, OUTFLAG_DRAIN = 0x20, OUTFLAG_OBJECT_EXISTS = 0x08, - INFLAG_INSIDE = 0x08, - FLAG_WATER = 0x40, FLAG_AUTOEXECUTE_EVENT = 0x10, + INFLAG_INSIDE = 0x08, FLAG_AUTOEXECUTE_EVENT = 0x10, + RESTRICTION_ETHERIALIZE = 0x40, RESTRICTION_80 = 0x80, + RESTRICTION_TOWN_PORTAL = 0x100, RESTRICTION_SUPER_SHELTER = 0x200, + RESTRICTION_TIME_DISTORTION = 0x400, RESTRICTION_LLOYDS_BEACON = 0x800, + RESTRICTION_TELPORT = 0x1000, RESTRICTION_2000 = 0x2000, + RESTRICTION_REST = 0x4000, RESTRICTION_SAVE = 0x8000, + FLAG_GROUND_BITS = 7 }; diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index be8f4e6e18..ff59ed9b18 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -102,6 +102,7 @@ Party::Party(XeenEngine *vm) { _falling = false; _fallMaze = 0; _fallDamage = 0; + _dead = false; } void Party::synchronize(Common::Serializer &s) { @@ -360,7 +361,7 @@ void Party::addTime(int numMinutes) { if (_newDay && _minutes >= 300) { if (_vm->_mode != MODE_9 && _vm->_mode != MODE_17) { resetTemps(); - if (_rested || _vm->_mode == MODE_5) { + if (_rested || _vm->_mode == MODE_SLEEPING) { _rested = false; } else { for (int idx = 0; idx < _partyCount; ++idx) { @@ -497,4 +498,19 @@ void Party::notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wa ErrorScroll::show(_vm, msg, wait); } +void Party::checkPartyDead() { + bool inCombat = _vm->_mode == MODE_COMBAT; + + for (uint charIdx = 0; charIdx < (inCombat ? _combatParty.size() : _activeParty.size()); ++charIdx) { + Character &c = inCombat ? *_combatParty[charIdx] : _activeParty[charIdx]; + Condition cond = c.worstCondition(); + if (cond <= CONFUSED || cond == NO_CONDITION) { + _dead = false; + return; + } + } + + _dead = true; +} + } // End of namespace Xeen diff --git a/engines/xeen/party.h b/engines/xeen/party.h index b1ca067df4..5b7da052ba 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -125,6 +125,7 @@ public: int _fallMaze; int _fallDamage; DamageType _damageType; + bool _dead; public: Party(XeenEngine *vm); @@ -147,6 +148,8 @@ public: int subtract(int mode, uint amount, int whereId, ErrorWaitType wait = WT_FREEZE_WAIT); void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait); + + void checkPartyDead(); }; } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 204e727326..d127ddcfc4 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1423,4 +1423,13 @@ const char *const AUTO_NOTES_DATA = "%s\x3l\n" "%s\x3l"; +const char *const REST_COMPLETE = + "\v000\t0008 hours pass. Rest complete.\n" + "%s\n" + "%d food consumed."; +const char *const PARTY_IS_STARVING = "\f07The Party is Starving!\fd"; +const char *const HIT_SPELL_POINTS_RESTORED = "Hit Pts and Spell Pts restored."; +const char *const TOO_DANGEROUS_TO_REST = "Too dangerous to rest here!"; +const char *const SOME_CHARS_MAY_DIE = "Some Chars may die. Rest anyway?"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 9c0136c06f..517d6e4caf 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -486,6 +486,12 @@ extern const char *const QUEST_ITEMS_DATA; extern const char *const CURRENT_QUESTS_DATA; extern const char *const AUTO_NOTES_DATA; +extern const char *const REST_COMPLETE; +extern const char *const PARTY_IS_STARVING; +extern const char *const HIT_SPELL_POINTS_RESTORED; +extern const char *const TOO_DANGEROUS_TO_REST; +extern const char *const SOME_CHARS_MAY_DIE; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 50e77668cd..4943d95d2a 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -92,7 +92,7 @@ void Spells::doSpell(int spellId) { &Spells::implosion, &Spells::starBurst, &Spells::divineIntervention }; - if (_vm->_mode == MODE_InCombat) { + if (_vm->_mode == MODE_COMBAT) { if (spellId == 15 || spellId == 20 || spellId == 27 || spellId == 41 || spellId == 47 || spellId == 54 || spellId == 57) { ErrorDialog::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED, diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index af2044b212..537768e7e5 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -78,15 +78,16 @@ enum Mode { MODE_FF = -1, MODE_0 = 0, MODE_1 = 1, - MODE_InCombat = 2, + MODE_COMBAT = 2, MODE_3 = 3, MODE_4 = 4, - MODE_5 = 5, + MODE_SLEEPING = 5, MODE_6 = 6, MODE_7 = 7, MODE_8 = 8, MODE_9 = 9, MODE_CHARACTER_INFO = 10, + MODE_12 = 12, MODE_17 = 17 }; -- cgit v1.2.3 From a381c49c4dddb1c8bb211b9fcaa1aec94410772c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 Feb 2015 22:47:28 -0500 Subject: XEEN: Implemented bashing --- engines/xeen/character.cpp | 28 +++++++++++ engines/xeen/character.h | 2 + engines/xeen/events.cpp | 8 +++ engines/xeen/events.h | 2 + engines/xeen/interface.cpp | 116 +++++++++++++++++++++++++++++++++++++++++++ engines/xeen/interface.h | 2 + engines/xeen/interface_map.h | 2 +- 7 files changed, 159 insertions(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index 4e4a4da697..fb1447d84c 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -1757,5 +1757,33 @@ int Character::makeItem(int p1, int itemIndex, int p3) { return category; } +void Character::subtractHitPoints(int amount) { + SoundManager &sound = *Party::_vm->_sound; + _currentHp -= amount; + bool flag = _currentHp <= 10; + + if (_currentHp < 1) { + int v = getMaxHP() + _currentHp; + if (v >= 1) { + _conditions[UNCONSCIOUS] = 1; + sound.playFX(38);; + } else { + _conditions[DEAD] = 1; + flag = true; + if (_currentHp > 0) + _currentHp = 0; + } + + if (flag) { + // Check for breaking equipped armor + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + XeenItem &item = _armor[idx]; + if (item._id && item._frame) + item._bonusFlags |= ITEMFLAG_BROKEN; + } + } + } +} + } // End of namespace Xeen diff --git a/engines/xeen/character.h b/engines/xeen/character.h index c9a787cbc5..7fc13f1015 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -309,6 +309,8 @@ public: int getNumAwards() const; int makeItem(int p1, int itemIndex, int p3); + + void subtractHitPoints(int amount); }; } // End of namespace Xeen diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp index e0c3b26dc6..89a1ac3b50 100644 --- a/engines/xeen/events.cpp +++ b/engines/xeen/events.cpp @@ -168,6 +168,14 @@ bool EventsManager::wait(uint numFrames, bool interruptable) { return false; } +void EventsManager::ipause(int amount) { + updateGameCounter(); + do { + _vm->_interface->draw3d(true); + pollEventsAndWait(); + } while (!_vm->shouldQuit() && timeElapsed() < amount); +} + /** * Handles moving to the next game frame */ diff --git a/engines/xeen/events.h b/engines/xeen/events.h index 1705bb43d3..5d6918b0da 100644 --- a/engines/xeen/events.h +++ b/engines/xeen/events.h @@ -90,6 +90,8 @@ public: uint32 timeElapsed5() const { return _frameCounter - _gameCounters[5]; } bool wait(uint numFrames, bool interruptable = false); + + void ipause(int amount); }; class GameEvent { diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index c31ff844d9..0d734aa0ce 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -695,6 +695,32 @@ void Interface::perform() { _vm->_moveMonsters = true; break; + case Common::KEYCODE_b: + chargeStep(); + + if (map.getCell(2) < map.mazeData()._difficulties._wallNoPass + && !map._isOutdoors) { + switch (party._mazeDirection) { + case DIR_NORTH: + ++party._mazePosition.y; + break; + case DIR_EAST: + ++party._mazePosition.x; + break; + case DIR_SOUTH: + --party._mazePosition.y; + break; + case DIR_WEST: + --party._mazePosition.x; + break; + } + chargeStep(); + stepTime(); + } else { + bash(party._mazePosition, party._mazeDirection); + } + break; + case Common::KEYCODE_i: // Show Info dialog _vm->_moveMonsters = false; @@ -1086,4 +1112,94 @@ void Interface::rest() { } } +void Interface::bash(const Common::Point &pt, Direction direction) { + EventsManager &events = *_vm->_events; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + + if (map._isOutdoors) + return; + + sound.playFX(31); + + uint charNum1 = 0, charNum2 = 0; + for (uint charIdx = 0; charIdx < party._activeParty.size(); ++charIdx) { + Character &c = party._activeParty[charIdx]; + Condition condition = c.worstCondition(); + + if (!(condition == ASLEEP || (condition >= PARALYZED && + condition <= ERADICATED))) { + if (charNum1) { + charNum2 = charIdx + 1; + break; + } else { + charNum1 = charIdx + 1; + } + } + } + + party._activeParty[charNum1 - 1].subtractHitPoints(2); + _charPowSprites.draw(screen._windows[0], 0, + Common::Point(CHAR_FACES_X[charNum1 - 1], 150)); + screen._windows[0].update(); + + if (charNum2) { + party._activeParty[charNum2 - 1].subtractHitPoints(2); + _charPowSprites.draw(screen._windows[0], 0, + Common::Point(CHAR_FACES_X[charNum2 - 1], 150)); + screen._windows[0].update(); + } + + int cell = map.mazeLookup(Common::Point(pt.x + SCREEN_POSITIONING_X[direction][7], + pt.y + SCREEN_POSITIONING_Y[direction][7]), 0, 0xffff); + if (cell != INVALID_CELL) { + int v = map.getCell(2); + + if (v == 7) { + ++_wo[207]; + ++_wo[267]; + ++_wo[287]; + } else if (v == 14) { + ++_wo[267]; + ++_wo[287]; + } else if (v == 15) { + ++_wo[287]; + } else { + int might = party._activeParty[charNum1 - 1].getStat(MIGHT) + + _vm->getRandomNumber(1, 30); + if (charNum2) + might += party._activeParty[charNum2 - 1].getStat(MIGHT); + + int bashThreshold = (v == 9) ? map.mazeData()._difficulties._bashGrate : + map.mazeData()._difficulties._bashWall; + if (might >= bashThreshold) { + // Remove the wall on the current cell, and the reverse wall + // on the cell we're bashing through to + map.setWall(pt, direction, 3); + switch (direction) { + case DIR_NORTH: + map.setWall(Common::Point(pt.x, pt.y + 1), DIR_SOUTH, 3); + break; + case DIR_EAST: + map.setWall(Common::Point(pt.x + 1, pt.y), DIR_WEST, 3); + break; + case DIR_SOUTH: + map.setWall(Common::Point(pt.x, pt.y - 1), DIR_NORTH, 3); + break; + case DIR_WEST: + map.setWall(Common::Point(pt.x - 1, pt.y), DIR_EAST, 3); + break; + } + } + } + } + + party.checkPartyDead(); + events.ipause(2); + charIconsPrint(true); +} + + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index cecc5c3a58..9d7cb5cd4f 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -106,6 +106,8 @@ public: void perform(); void rest(); + + void bash(const Common::Point &pt, Direction direction); }; } // End of namespace Xeen diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 197f239404..034d1a6746 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -96,7 +96,6 @@ private: SpriteResource _spellFxSprites; SpriteResource _fecpSprites; SpriteResource _blessSprites; - SpriteResource _charPowSprites; int _combatFloatCounter; void initDrawStructs(); @@ -130,6 +129,7 @@ protected: public: OutdoorDrawList _outdoorList; IndoorDrawList _indoorList; + SpriteResource _charPowSprites; SpriteResource _globalSprites; bool _upDoorText; Common::String _screenText; -- cgit v1.2.3 From ccb224d89ae4fcb889adc4e53062e90d9318851c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 8 Feb 2015 16:03:13 -0500 Subject: XEEN: In progress Dismiss dialog --- engines/xeen/dialogs_dismiss.cpp | 99 ++++++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_dismiss.h | 47 +++++++++++++++++++ engines/xeen/interface.cpp | 17 +++++++ engines/xeen/interface.h | 2 + engines/xeen/module.mk | 1 + engines/xeen/resources.cpp | 2 + engines/xeen/resources.h | 2 + 7 files changed, 170 insertions(+) create mode 100644 engines/xeen/dialogs_dismiss.cpp create mode 100644 engines/xeen/dialogs_dismiss.h (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_dismiss.cpp b/engines/xeen/dialogs_dismiss.cpp new file mode 100644 index 0000000000..304c7a0cef --- /dev/null +++ b/engines/xeen/dialogs_dismiss.cpp @@ -0,0 +1,99 @@ +/* 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 "xeen/dialogs_dismiss.h" +#include "xeen/party.h" +#include "xeen/resources.h" +#include "xeen/xeen.h" + +namespace Xeen { + +void Dismiss::show(XeenEngine *vm) { + Dismiss *dlg = new Dismiss(vm); + dlg->execute(); + delete dlg; +} + +void Dismiss::execute() { + Screen &screen = *_vm->_screen; + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + loadButtons(); + + Window &w = screen._windows[31]; + w.open(); + _iconSprites.draw(w, 0, Common::Point(225, 120)); + w.update(); + + while (!_vm->shouldQuit()) { + do { + events.updateGameCounter(); + intf.draw3d(false); + w.frame(); + w.writeString("\r"); + _iconSprites.draw(w, 0, Common::Point(225, 120)); + screen._windows[3].update(); + w.update(); + + do { + events.pollEventsAndWait(); + checkEvents(_vm); + } while (!_vm->shouldQuit() && !_buttonValue && events.timeElapsed() == 0); + } while (!_vm->shouldQuit() && !_buttonValue); + + if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) { + _buttonValue -= Common::KEYCODE_F1; + + if (_buttonValue < (int)party._activeParty.size()) { + if (party._activeParty.size() == 1) { + w.close(); + ErrorScroll::show(_vm, CANT_DISMISS_LAST_CHAR, WT_NONFREEZED_WAIT); + w.open(); + } else { + Character tempChar = party._activeParty[_buttonValue]; + int charIndex = party._partyMembers[_buttonValue]; + intf._partyFaces[_buttonValue] = 0; + + intf.sortFaces(); +// party.sortParty(); + + // TODO + } + break; + } + } else if (_buttonValue == Common::KEYCODE_ESCAPE) { + + } + } +} + +void Dismiss::loadButtons() { + _iconSprites.load("esc.icn"); + addButton(Common::Rect(225, 120, 249, 140), Common::KEYCODE_ESCAPE, &_iconSprites); + addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_iconSprites, false); + addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_iconSprites, false); + addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3, &_iconSprites, false); + addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4, &_iconSprites, false); +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_dismiss.h b/engines/xeen/dialogs_dismiss.h new file mode 100644 index 0000000000..ec40e87f7c --- /dev/null +++ b/engines/xeen/dialogs_dismiss.h @@ -0,0 +1,47 @@ +/* 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 XEEN_DIALOGS_DISMISS_H +#define XEEN_DIALOGS_DISMISS_H + +#include "xeen/dialogs.h" +#include "xeen/party.h" + +namespace Xeen { + +class Dismiss : public ButtonContainer { +private: + XeenEngine *_vm; + SpriteResource _iconSprites; + + Dismiss(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + void execute(); + + void loadButtons(); +public: + static void show(XeenEngine *vm); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_DISMISS_H */ diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 0d734aa0ce..b51801fd58 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -385,6 +385,23 @@ void Interface::charIconsPrint(bool updateFlag) { screen._windows[33].update(); } +/** + * Removes any empty character entries from the faces list + */ +void Interface::sortFaces() { + for (uint charIdx = 0; charIdx < MAX_ACTIVE_PARTY; ++charIdx) { + if (!_partyFaces[charIdx]) { + for (uint charIdx2 = charIdx + 1; charIdx2 < 8; ++charIdx2) { + if (_partyFaces[charIdx2]) { + _partyFaces[charIdx] = _partyFaces[charIdx2]; + _partyFaces[charIdx2] = 0; + break; + } + } + } + } +} + void Interface::drawViewBackground(int bgType) { if (bgType >= 4) return; diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 9d7cb5cd4f..0f5ca18780 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -97,6 +97,8 @@ public: void charIconsPrint(bool updateFlag); + void sortFaces(); + void doFalling(); void highlightChar(int charId); diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 8c526b4e46..50d7891ad2 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -12,6 +12,7 @@ MODULE_OBJS := \ automap.o \ dialogs_automap.o \ dialogs_char_info.o \ + dialogs_dismiss.o \ dialogs_error.o \ dialogs_exchange.o \ dialogs_options.o \ diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index d127ddcfc4..11b209274d 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1432,4 +1432,6 @@ const char *const HIT_SPELL_POINTS_RESTORED = "Hit Pts and Spell Pts restored."; const char *const TOO_DANGEROUS_TO_REST = "Too dangerous to rest here!"; const char *const SOME_CHARS_MAY_DIE = "Some Chars may die. Rest anyway?"; +const char *const CANT_DISMISS_LAST_CHAR = "You cannot dismiss your last character!"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 517d6e4caf..f7609bc2cd 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -492,6 +492,8 @@ extern const char *const HIT_SPELL_POINTS_RESTORED; extern const char *const TOO_DANGEROUS_TO_REST; extern const char *const SOME_CHARS_MAY_DIE; +extern const char *const CANT_DISMISS_LAST_CHAR; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From 62eb39515b0f19a52861e9dd0fb4ac6af8c1c2ba Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 9 Feb 2015 20:57:19 -0500 Subject: XEEN: Some refactoring needed for resources the party dialog will need --- engines/xeen/dialogs_party.cpp | 153 +++++++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_party.h | 58 ++++++++++++++++ engines/xeen/events.cpp | 2 +- engines/xeen/events.h | 2 +- engines/xeen/interface.cpp | 139 +++---------------------------------- engines/xeen/interface.h | 4 -- engines/xeen/module.mk | 1 + engines/xeen/resources.cpp | 6 ++ engines/xeen/resources.h | 2 + engines/xeen/scripts.cpp | 2 +- engines/xeen/scripts.h | 2 +- engines/xeen/town.cpp | 7 +- engines/xeen/xeen.cpp | 6 +- engines/xeen/xeen.h | 1 + 14 files changed, 242 insertions(+), 143 deletions(-) create mode 100644 engines/xeen/dialogs_party.cpp create mode 100644 engines/xeen/dialogs_party.h (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp new file mode 100644 index 0000000000..510cd6572d --- /dev/null +++ b/engines/xeen/dialogs_party.cpp @@ -0,0 +1,153 @@ +/* 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/scummsys.h" +#include "xeen/dialogs_party.h" +#include "xeen/character.h" +#include "xeen/events.h" +#include "xeen/party.h" +#include "xeen/xeen.h" + +namespace Xeen { + + void PartyDialog::show(XeenEngine *vm) { + PartyDialog *dlg = new PartyDialog(vm); + dlg->execute(); + delete dlg; +} + +void PartyDialog::execute() { + EventsManager &events = *_vm->_events; + Map &map = *_vm->_map; + Screen &screen = *_vm->_screen; + + loadButtons(); + setupBackground(); + + _vm->_mode = MODE_1; + Common::Array<int> xeenSideChars; + + // Build up a list of characters on the same Xeen side being loaded + for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { + Character &player = _vm->_roster[i]; + if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0)) + continue; + + xeenSideChars.push_back(i); + } + + Window &w = screen._windows[11]; + w.open(); + setupFaces(0, xeenSideChars, false); + w.writeString(_displayText); + w.drawList(&_faceDrawStructs[0], 4); + + _iconSprites.draw(w, 0, Common::Point(16, 100)); + _iconSprites.draw(w, 2, Common::Point(52, 100)); + _iconSprites.draw(w, 4, Common::Point(87, 100)); + _iconSprites.draw(w, 6, Common::Point(122, 100)); + _iconSprites.draw(w, 8, Common::Point(157, 100)); + _iconSprites.draw(w, 10, Common::Point(192, 100)); + + screen.loadPalette("mm4.pal"); + // TODO +} + +void PartyDialog::loadButtons() { + _iconSprites.load("inn.icn"); + addButton(Common::Rect(16, 100, 40, 120), Common::KEYCODE_UP, &_iconSprites); + addButton(Common::Rect(52, 100, 76, 120), Common::KEYCODE_DOWN, &_iconSprites); + addButton(Common::Rect(87, 100, 111, 120), Common::KEYCODE_d, &_iconSprites); + addButton(Common::Rect(122, 100, 146, 120), Common::KEYCODE_r, &_iconSprites); + addButton(Common::Rect(157, 100, 181, 120), Common::KEYCODE_c, &_iconSprites); + addButton(Common::Rect(192, 100, 116, 120), Common::KEYCODE_x, &_iconSprites); + addButton(Common::Rect(0, 0, 0, 0), Common::KEYCODE_ESCAPE, &_iconSprites, false); + addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_iconSprites, false); + addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_iconSprites, false); + addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3, &_iconSprites, false); + addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4, &_iconSprites, false); +} + +void PartyDialog::initDrawStructs() { + _faceDrawStructs[0] = DrawStruct(0, 0, 0); + _faceDrawStructs[1] = DrawStruct(0, 101, 0); + _faceDrawStructs[2] = DrawStruct(0, 0, 43); + _faceDrawStructs[3] = DrawStruct(0, 101, 43); +} + +void PartyDialog::setupBackground() { + _vm->_screen->loadBackground("back.raw"); + _vm->_interface->assembleBorder(); +} + +/** + * Sets up the faces for display in the party dialog + */ +void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag) { + Resources &res = *_vm->_resources; + Common::String charNames[4]; + Common::String charRaces[4]; + Common::String charSex[4]; + Common::String charClasses[4]; + int posIndex; + int charId; + + for (posIndex = 0; posIndex < 4; ++posIndex) { + charId = xeenSideChars[charIndex]; + bool isInParty = _vm->_party->isInParty(charId); + + if (charId == 0xff) { + while ((int)_buttons.size() >(7 + posIndex)) + _buttons.remove_at(_buttons.size() - 1); + break; + } + + Common::Rect &b = _buttons[7 + posIndex]._bounds; + b.moveTo((posIndex & 1) ? 117 : 16, b.top); + Character &ps = _vm->_roster[xeenSideChars[charIndex + posIndex]]; + charNames[posIndex] = isInParty ? IN_PARTY : ps._name; + charRaces[posIndex] = RACE_NAMES[ps._race]; + charSex[posIndex] = SEX_NAMES[ps._sex]; + charClasses[posIndex] = CLASS_NAMES[ps._class]; + } + + charIconsPrint(updateFlag); + + // Set up the sprite set to use for each face + charId = xeenSideChars[charIndex]; + _faceDrawStructs[0]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId]; + charId = xeenSideChars[charIndex + 1]; + _faceDrawStructs[1]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId]; + charId = xeenSideChars[charIndex + 2]; + _faceDrawStructs[2]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId]; + charId = xeenSideChars[charIndex + 3]; + _faceDrawStructs[3]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId]; + + _displayText = Common::String::format(PARTY_DETAILS, + charNames[0].c_str(), charRaces[0].c_str(), charSex[0].c_str(), charClasses[0].c_str(), + charNames[1].c_str(), charRaces[1].c_str(), charSex[1].c_str(), charClasses[1].c_str(), + charNames[2].c_str(), charRaces[2].c_str(), charSex[2].c_str(), charClasses[2].c_str(), + charNames[3].c_str(), charRaces[3].c_str(), charSex[3].c_str(), charClasses[3].c_str() + ); +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h new file mode 100644 index 0000000000..c2768e9994 --- /dev/null +++ b/engines/xeen/dialogs_party.h @@ -0,0 +1,58 @@ +/* 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 XEEN_DIALOGS_PARTY_H +#define XEEN_DIALOGS_PARTY_H + +#include "xeen/dialogs.h" +#include "xeen/screen.h" +#include "xeen/sprites.h" + +namespace Xeen { + +class PartyDialog : public ButtonContainer { +private: + XeenEngine *_vm; + SpriteResource _iconSprites; + DrawStruct _faceDrawStructs[4]; + Common::String _displayText; + + PartyDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + void execute(); + + void loadButtons(); + + void initDrawStructs(); + + void setupBackground(); + + void charIconsPrint(bool updateFlag); + + void setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag); +public: + static void show(XeenEngine *vm); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_PARTY_H */ diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp index 89a1ac3b50..9f13861dd2 100644 --- a/engines/xeen/events.cpp +++ b/engines/xeen/events.cpp @@ -168,7 +168,7 @@ bool EventsManager::wait(uint numFrames, bool interruptable) { return false; } -void EventsManager::ipause(int amount) { +void EventsManager::ipause(uint amount) { updateGameCounter(); do { _vm->_interface->draw3d(true); diff --git a/engines/xeen/events.h b/engines/xeen/events.h index 5d6918b0da..cce3155a4b 100644 --- a/engines/xeen/events.h +++ b/engines/xeen/events.h @@ -91,7 +91,7 @@ public: bool wait(uint numFrames, bool interruptable = false); - void ipause(int amount); + void ipause(uint amount); }; class GameEvent { diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index b51801fd58..a88217e5ad 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -46,11 +46,6 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm( void Interface::initDrawStructs() { - _faceDrawStructs[0] = DrawStruct(0, 0, 0); - _faceDrawStructs[1] = DrawStruct(0, 101, 0); - _faceDrawStructs[2] = DrawStruct(0, 0, 43); - _faceDrawStructs[3] = DrawStruct(0, 101, 43); - _mainList[0] = DrawStruct(7, 232, 74); _mainList[1] = DrawStruct(0, 235, 75); _mainList[2] = DrawStruct(2, 260, 75); @@ -85,70 +80,8 @@ void Interface::setup() { } void Interface::manageCharacters(bool soundPlayed) { - EventsManager &events = *_vm->_events; - Map &map = *_vm->_map; - Screen &screen = *_vm->_screen; - bool flag = false; - -start: - if (_vm->_party->_mazeId != 0) { - _vm->_mode = MODE_0; - _buttonsLoaded = true; - } else { - if (!soundPlayed) { - warning("TODO: loadSound?"); - } - - if (!_partyFaces[0]) { - // Xeen only uses 24 of possible 30 character slots - loadCharIcons(); - - for (int i = 0; i < _vm->_party->_partyCount; ++i) - _partyFaces[i] = &_charFaces[_vm->_party->_partyMembers[i]]; - } - - _vm->_mode = MODE_1; - Common::Array<int> xeenSideChars; - - // Build up a list of characters on the same Xeen side being loaded - for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { - Character &player = _vm->_roster[i]; - if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0)) - continue; - - xeenSideChars.push_back(i); - } - - // Add in buttons for the UI - _interfaceText = ""; - _buttonsLoaded = true; - addButton(Common::Rect(16, 100, 40, 120), 242, &_uiSprites, true); - addButton(Common::Rect(52, 100, 76, 120), 243, &_uiSprites, true); - addButton(Common::Rect(87, 100, 111, 120), 68, &_uiSprites, true); - addButton(Common::Rect(122, 100, 146, 120), 82, &_uiSprites, true); - addButton(Common::Rect(157, 100, 181, 120), 67, &_uiSprites, true); - addButton(Common::Rect(192, 100, 216, 120), 88, &_uiSprites, true); - addButton(Common::Rect(), 27, &_uiSprites, false); - addButton(Common::Rect(16, 16, 48, 48), 49, &_uiSprites, false); - addButton(Common::Rect(117, 16, 139, 48), 50, &_uiSprites, false); - addButton(Common::Rect(16, 59, 48, 81), 51, &_uiSprites, false); - addButton(Common::Rect(117, 59, 149, 81), 52, &_uiSprites, false); - - setupBackground(); - Window &w = screen._windows[11]; - w.open(); - setupFaces(0, xeenSideChars, false); - w.writeString(_interfaceText); - w.drawList(&_faceDrawStructs[0], 4); - - _uiSprites.draw(w, 0, Common::Point(16, 100)); - _uiSprites.draw(w, 2, Common::Point(52, 100)); - _uiSprites.draw(w, 4, Common::Point(87, 100)); - _uiSprites.draw(w, 6, Common::Point(122, 100)); - _uiSprites.draw(w, 8, Common::Point(157, 100)); - _uiSprites.draw(w, 10, Common::Point(192, 100)); - - screen.loadPalette("mm4.pal"); + /* + if (flag) { screen._windows[0].update(); @@ -264,76 +197,23 @@ start: for (int i = 0; i < TOTAL_CHARACTERS; ++i) _charFaces[i].clear(); + */ } void Interface::loadCharIcons() { - for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { - // Load new character resource - Common::String name = Common::String::format("char%02d.fac", i + 1); - _charFaces[i].load(name); - } - _dseFace.load("dse.fac"); } void Interface::loadPartyIcons() { - for (int i = 0; i < _vm->_party->_partyCount; ++i) - _partyFaces[i] = &_charFaces[_vm->_party->_partyMembers[i]]; -} - -void Interface::setupBackground() { - _vm->_screen->loadBackground("back.raw"); - assembleBorder(); -} - -void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag) { - Common::String playerNames[4]; - Common::String playerRaces[4]; - Common::String playerSex[4]; - Common::String playerClass[4]; - int posIndex; - int charId; - - for (posIndex = 0; posIndex < 4; ++posIndex) { - charId = xeenSideChars[charIndex]; - bool isInParty = _vm->_party->isInParty(charId); - - if (charId == 0xff) { - while ((int)_buttons.size() > (7 + posIndex)) - _buttons.remove_at(_buttons.size() - 1); - break; - } - - Common::Rect &b = _buttons[7 + posIndex]._bounds; - b.moveTo((posIndex & 1) ? 117 : 16, b.top); - Character &ps = _vm->_roster[xeenSideChars[charIndex + posIndex]]; - playerNames[posIndex] = isInParty ? IN_PARTY : ps._name; - playerRaces[posIndex] = RACE_NAMES[ps._race]; - playerSex[posIndex] = SEX_NAMES[ps._sex]; - playerClass[posIndex] = CLASS_NAMES[ps._class]; - } + Party &party = *_vm->_party; + Resources &res = *_vm->_resources; - charIconsPrint(updateFlag); - - // Set up the sprite set to use for each face - charId = xeenSideChars[charIndex]; - _faceDrawStructs[0]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId]; - charId = xeenSideChars[charIndex + 1]; - _faceDrawStructs[1]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId]; - charId = xeenSideChars[charIndex + 2]; - _faceDrawStructs[2]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId]; - charId = xeenSideChars[charIndex + 3]; - _faceDrawStructs[3]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId]; - - _interfaceText = Common::String::format(PARTY_DETAILS, - playerNames[0].c_str(), playerRaces[0].c_str(), playerSex[0].c_str(), playerClass[0].c_str(), - playerNames[1].c_str(), playerRaces[1].c_str(), playerSex[1].c_str(), playerClass[1].c_str(), - playerNames[2].c_str(), playerRaces[2].c_str(), playerSex[2].c_str(), playerClass[2].c_str(), - playerNames[3].c_str(), playerRaces[3].c_str(), playerSex[3].c_str(), playerClass[3].c_str() - ); + for (int i = 0; i < party._partyCount; ++i) + _partyFaces[i] = &res._charFaces[_vm->_party->_partyMembers[i]]; } void Interface::charIconsPrint(bool updateFlag) { + Resources &res = *_vm->_resources; Screen &screen = *_vm->_screen; bool stateFlag = _vm->_mode == MODE_COMBAT; _restoreSprites.draw(screen, 0, Common::Point(8, 149)); @@ -346,8 +226,7 @@ void Interface::charIconsPrint(bool updateFlag) { Condition charCondition = ps.worstCondition(); int charFrame = FACE_CONDITION_FRAMES[charCondition]; - SpriteResource *sprites = (charFrame > 4 && !_charFaces[0].empty()) ? - &_dseFace : _partyFaces[charIndex]; + SpriteResource *sprites = (charFrame > 4) ? &_dseFace : _partyFaces[charIndex]; if (charFrame > 4) charFrame -= 5; diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 0f5ca18780..9ab9102374 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -44,8 +44,6 @@ private: SpriteResource _hpSprites; SpriteResource _uiSprites; SpriteResource _iconSprites; - SpriteResource _charFaces[TOTAL_CHARACTERS]; - DrawStruct _faceDrawStructs[4]; DrawStruct _mainList[16]; int _combatCharIds[8]; @@ -59,8 +57,6 @@ private: void setupBackground(); - void setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag); - void drawViewBackground(int bgType); void moveCharacterToRoster(); diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 50d7891ad2..083abb9a8c 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -19,6 +19,7 @@ MODULE_OBJS := \ dialogs_info.o \ dialogs_input.o \ dialogs_items.o \ + dialogs_party.o \ dialogs_query.o \ dialogs_quests.o \ dialogs_quick_ref.o \ diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 11b209274d..7067886c87 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -31,6 +31,12 @@ Resources::Resources() { while (f.pos() < f.size()) _maeNames.push_back(f.readString()); f.close(); + + for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { + // Load new character resource + Common::String name = Common::String::format("char%02d.fac", i + 1); + _charFaces[i].load(name); + } } /*------------------------------------------------------------------------*/ diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index f7609bc2cd..dd3a77504a 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/str-array.h" #include "gui/debugger.h" +#include "xeen/party.h" #include "xeen/spells.h" namespace Xeen { @@ -34,6 +35,7 @@ class Resources { public: // Magic and equipment names Common::StringArray _maeNames; + SpriteResource _charFaces[TOTAL_CHARACTERS]; public: Resources(); }; diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 4859e93405..3837509760 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -107,7 +107,7 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) { _var50 = false; } -bool Scripts::checkEvents() { +int Scripts::checkEvents() { Combat &combat = *_vm->_combat; EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index d51cd0c26b..d353581497 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -233,7 +233,7 @@ public: public: Scripts(XeenEngine *vm); - bool checkEvents(); + int checkEvents(); void giveTreasure(); diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 3a07d2a9e0..c12973cbcd 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -630,6 +630,7 @@ Character *Town::doTavernOptions(Character *c) { } break; case Common::KEYCODE_f: { + // Food if (party._mazeId == (isDarkCc ? 29 : 28)) { _v22 = party._partyCount * 15; _v23 = 10; @@ -680,6 +681,7 @@ Character *Town::doTavernOptions(Character *c) { } case Common::KEYCODE_r: { + // Rumors if (party._mazeId == (isDarkCc ? 29 : 28)) { idx = 0; } else if (party._mazeId == (isDarkCc ? 31 : 30)) { @@ -701,8 +703,7 @@ Character *Town::doTavernOptions(Character *c) { } case Common::KEYCODE_s: { - // Save game - // TODO: This needs to be fit in better with ScummVM framework + // Sign In int idx = isDarkCc ? (party._mazeId - 29) >> 1 : party._mazeId - 28; assert(idx >= 0); party._mazePosition.x = TAVERN_EXIT_LIST[isDarkCc ? 1 : 0][_townActionId][idx][0]; @@ -723,7 +724,7 @@ Character *Town::doTavernOptions(Character *c) { party.addTime(1440); party._mazeId = 0; - _vm->quitGame(); + _vm->_quitMode = 2; break; } diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index d34e8edb21..ed944262e1 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -51,6 +51,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _spells = nullptr; _town = nullptr; _eventData = nullptr; + _quitMode = 0; _dangerSenseAllowed = false; _noDirectionSense = false; _moveMonsters = false; @@ -289,6 +290,7 @@ void XeenEngine::playGame() { */ void XeenEngine::play() { // TODO: Init variables + _quitMode = 0; _interface->setup(); _screen->loadBackground("back.raw"); @@ -331,8 +333,8 @@ void XeenEngine::gameLoop() { while (!shouldQuit()) { _map->cellFlagLookup(_party->_mazePosition); if (_map->_currentIsEvent) { - _scripts->checkEvents(); - if (shouldQuit()) + _quitMode = _scripts->checkEvents(); + if (shouldQuit() || _quitMode) return; } _scripts->giveTreasure(); diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 537768e7e5..4664998a3e 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -153,6 +153,7 @@ public: GameEvent _gameEvent; Common::SeekableReadStream *_eventData; Roster _roster; + int _quitMode; bool _dangerSenseAllowed; bool _noDirectionSense; bool _moveMonsters; -- cgit v1.2.3 From c798a555105c58f82d373b92b479a577d4215cb9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 9 Feb 2015 21:34:03 -0500 Subject: XEEN: More refactoring needed for party dialog setup --- engines/xeen/dialogs_party.cpp | 172 +++++++++++++++++++++++++++++++++++------ engines/xeen/interface.cpp | 137 +------------------------------- engines/xeen/interface.h | 2 - engines/xeen/party.cpp | 7 ++ engines/xeen/party.h | 3 + engines/xeen/saves.cpp | 8 +- engines/xeen/saves.h | 3 +- engines/xeen/xeen.cpp | 2 +- engines/xeen/xeen.h | 1 - 9 files changed, 168 insertions(+), 167 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index 510cd6572d..aa8d58f32b 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -38,38 +38,161 @@ namespace Xeen { void PartyDialog::execute() { EventsManager &events = *_vm->_events; Map &map = *_vm->_map; + Party &party = *_vm->_party; Screen &screen = *_vm->_screen; loadButtons(); setupBackground(); - _vm->_mode = MODE_1; - Common::Array<int> xeenSideChars; + while (!_vm->shouldQuit()) { + _vm->_mode = MODE_1; + Common::Array<int> xeenSideChars; - // Build up a list of characters on the same Xeen side being loaded - for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { - Character &player = _vm->_roster[i]; - if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0)) - continue; + party.loadActiveParty(); - xeenSideChars.push_back(i); + // Build up a list of characters on the same Xeen side being loaded + for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { + Character &player = party._roster[i]; + if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0)) + continue; + + xeenSideChars.push_back(i); + } + + Window &w = screen._windows[11]; + w.open(); + setupFaces(0, xeenSideChars, false); + w.writeString(_displayText); + w.drawList(&_faceDrawStructs[0], 4); + + _iconSprites.draw(w, 0, Common::Point(16, 100)); + _iconSprites.draw(w, 2, Common::Point(52, 100)); + _iconSprites.draw(w, 4, Common::Point(87, 100)); + _iconSprites.draw(w, 6, Common::Point(122, 100)); + _iconSprites.draw(w, 8, Common::Point(157, 100)); + _iconSprites.draw(w, 10, Common::Point(192, 100)); + screen.loadPalette("mm4.pal"); + + /* + + + if (flag) { + screen._windows[0].update(); + events.setCursor(0); + screen.fadeIn(4); + } else { + if (_vm->getGameID() == GType_DarkSide) { + screen.fadeOut(4); + screen._windows[0].update(); + } + + doScroll(_vm, false, false); + events.setCursor(0); + + if (_vm->getGameID() == GType_DarkSide) { + screen.fadeIn(4); + } + } + + // TODO + bool breakFlag = false; + while (!_vm->shouldQuit() && !breakFlag) { + events.pollEventsAndWait(); + checkEvents(_vm); + + switch (_buttonValue) { + case Common::KEYCODE_ESCAPE: + case Common::KEYCODE_SPACE: + case Common::KEYCODE_e: + case Common::KEYCODE_x: + if (_vm->_party->_partyCount == 0) { + ErrorScroll::show(_vm, NO_ONE_TO_ADVENTURE_WITH); + } else { + if (_vm->_mode != MODE_0) { + for (_intrIndex1 = 4; _intrIndex1 >= 0; --_intrIndex1) { + events.updateGameCounter(); + drawViewBackground(_intrIndex1); + w.update(); + + while (events.timeElapsed() < 1) + events.pollEventsAndWait(); + } + } + + w.close(); + _vm->_party->_realPartyCount = _vm->_party->_partyCount; + _vm->_party->_mazeId = _vm->_party->_priorMazeId; + + _vm->_party->copyPartyToRoster(_vm->_roster); + _vm->_saves->writeCharFile(); + breakFlag = true; + break; + } + break; + case Common::KEYCODE_1: + break; + case Common::KEYCODE_2: + break; + case Common::KEYCODE_3: + break; + case Common::KEYCODE_4: + break; + case Common::KEYCODE_c: + if (xeenSideChars.size() == 24) { + ErrorScroll::show(_vm, YOUR_ROSTER_IS_FULL); + } else { + screen.fadeOut(4); + w.close(); + moveCharacterToRoster(); + _vm->_saves->writeCharFile(); + screen.fadeOut(4); + flag = true; + _buttonsLoaded = true; + goto start; + } + break; + case Common::KEYCODE_d: + break; + case Common::KEYCODE_r: + if (_vm->_party->_partyCount > 0) { + // TODO + } + break; + case 201: + // TODO + break; + case 202: + // TODO + break; + case 203: + // TODO + break; + case 204: + // TODO + break; + case 205: + // TODO + break; + case 206: + // TODO + break; + case 242: + // TODO + break; + case 243: + // TODO + break; + default: + break; + } + } } - Window &w = screen._windows[11]; - w.open(); - setupFaces(0, xeenSideChars, false); - w.writeString(_displayText); - w.drawList(&_faceDrawStructs[0], 4); - - _iconSprites.draw(w, 0, Common::Point(16, 100)); - _iconSprites.draw(w, 2, Common::Point(52, 100)); - _iconSprites.draw(w, 4, Common::Point(87, 100)); - _iconSprites.draw(w, 6, Common::Point(122, 100)); - _iconSprites.draw(w, 8, Common::Point(157, 100)); - _iconSprites.draw(w, 10, Common::Point(192, 100)); - - screen.loadPalette("mm4.pal"); - // TODO + for (int i = 0; i < TOTAL_CHARACTERS; ++i) + _charFaces[i].clear(); + */ + // TODO + } } void PartyDialog::loadButtons() { @@ -103,6 +226,7 @@ void PartyDialog::setupBackground() { * Sets up the faces for display in the party dialog */ void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag) { + Party &party = *_vm->_party; Resources &res = *_vm->_resources; Common::String charNames[4]; Common::String charRaces[4]; @@ -123,7 +247,7 @@ void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bo Common::Rect &b = _buttons[7 + posIndex]._bounds; b.moveTo((posIndex & 1) ? 117 : 16, b.top); - Character &ps = _vm->_roster[xeenSideChars[charIndex + posIndex]]; + Character &ps = party._roster[xeenSideChars[charIndex + posIndex]]; charNames[posIndex] = isInParty ? IN_PARTY : ps._name; charRaces[posIndex] = RACE_NAMES[ps._race]; charSex[posIndex] = SEX_NAMES[ps._sex]; diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index a88217e5ad..8aa938b583 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -69,139 +69,11 @@ void Interface::setup() { _restoreSprites.load("restorex.icn"); _hpSprites.load("hpbars.icn"); _uiSprites.load("inn.icn"); - - // Get mappings to the active characters in the party - _vm->_party->_activeParty.resize(_vm->_party->_partyCount); - for (int i = 0; i < _vm->_party->_partyCount; ++i) { - _vm->_party->_activeParty[i] = _vm->_roster[_vm->_party->_partyMembers[i]]; - } - - _vm->_party->_newDay = _vm->_party->_minutes >= 300; -} - -void Interface::manageCharacters(bool soundPlayed) { - /* - - - if (flag) { - screen._windows[0].update(); - events.setCursor(0); - screen.fadeIn(4); - } else { - if (_vm->getGameID() == GType_DarkSide) { - screen.fadeOut(4); - screen._windows[0].update(); - } - - doScroll(_vm, false, false); - events.setCursor(0); - - if (_vm->getGameID() == GType_DarkSide) { - screen.fadeIn(4); - } - } - - // TODO - bool breakFlag = false; - while (!_vm->shouldQuit() && !breakFlag) { - events.pollEventsAndWait(); - checkEvents(_vm); - - switch (_buttonValue) { - case Common::KEYCODE_ESCAPE: - case Common::KEYCODE_SPACE: - case Common::KEYCODE_e: - case Common::KEYCODE_x: - if (_vm->_party->_partyCount == 0) { - ErrorScroll::show(_vm, NO_ONE_TO_ADVENTURE_WITH); - } else { - if (_vm->_mode != MODE_0) { - for (_intrIndex1 = 4; _intrIndex1 >= 0; --_intrIndex1) { - events.updateGameCounter(); - drawViewBackground(_intrIndex1); - w.update(); - - while (events.timeElapsed() < 1) - events.pollEventsAndWait(); - } - } - - w.close(); - _vm->_party->_realPartyCount = _vm->_party->_partyCount; - _vm->_party->_mazeId = _vm->_party->_priorMazeId; - - _vm->_party->copyPartyToRoster(_vm->_roster); - _vm->_saves->writeCharFile(); - breakFlag = true; - break; - } - break; - case Common::KEYCODE_1: - break; - case Common::KEYCODE_2: - break; - case Common::KEYCODE_3: - break; - case Common::KEYCODE_4: - break; - case Common::KEYCODE_c: - if (xeenSideChars.size() == 24) { - ErrorScroll::show(_vm, YOUR_ROSTER_IS_FULL); - } else { - screen.fadeOut(4); - w.close(); - moveCharacterToRoster(); - _vm->_saves->writeCharFile(); - screen.fadeOut(4); - flag = true; - _buttonsLoaded = true; - goto start; - } - break; - case Common::KEYCODE_d: - break; - case Common::KEYCODE_r: - if (_vm->_party->_partyCount > 0) { - // TODO - } - break; - case 201: - // TODO - break; - case 202: - // TODO - break; - case 203: - // TODO - break; - case 204: - // TODO - break; - case 205: - // TODO - break; - case 206: - // TODO - break; - case 242: - // TODO - break; - case 243: - // TODO - break; - default: - break; - } - } - } - - for (int i = 0; i < TOTAL_CHARACTERS; ++i) - _charFaces[i].clear(); - */ -} - -void Interface::loadCharIcons() { _dseFace.load("dse.fac"); + + Party &party = *_vm->_party; + party.loadActiveParty(); + party._newDay = party._minutes >= 300; } void Interface::loadPartyIcons() { @@ -304,7 +176,6 @@ void Interface::moveCharacterToRoster() { void Interface::startup() { Screen &screen = *_vm->_screen; - loadCharIcons(); _iconSprites.load("main.icn"); animate3d(); diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 9ab9102374..cce2eaaa30 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -83,8 +83,6 @@ public: void manageCharacters(bool soundPlayed); - void loadCharIcons(); - void loadPartyIcons(); void startup(); diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index ff59ed9b18..5cf5181142 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -186,6 +186,13 @@ void Party::synchronize(Common::Serializer &s) { s.syncBytes(&dummy[0], 30); } +void Party::loadActiveParty() { + _activeParty.resize(_partyCount); + for (int i = 0; i < _partyCount; ++i) { + _activeParty[i] = _roster[_partyMembers[i]]; + } +} + bool Party::checkSkill(Skill skillId) { uint total = 0; for (uint i = 0; i < _activeParty.size(); ++i) { diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 5b7da052ba..1382969477 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -113,6 +113,7 @@ public: bool _characterFlags[30][24]; public: // Other party related runtime data + Roster _roster; Common::Array<Character> _activeParty; Common::Array<Character *> _combatParty; int _combatPartyCount; @@ -131,6 +132,8 @@ public: void synchronize(Common::Serializer &s); + void loadActiveParty(); + bool checkSkill(Skill skillId); bool isInParty(int charId); diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index 85ab60bc12..61022a31cb 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -45,8 +45,8 @@ void OutFile::finalize() { /*------------------------------------------------------------------------*/ -SavesManager::SavesManager(XeenEngine *vm, Party &party, Roster &roster) : - BaseCCArchive(), _vm(vm), _party(party), _roster(roster) { +SavesManager::SavesManager(XeenEngine *vm, Party &party) : + BaseCCArchive(), _vm(vm), _party(party) { SearchMan.add("saves", this, 0, false); _data = nullptr; _wonWorld = false; @@ -113,7 +113,7 @@ void SavesManager::load(Common::SeekableReadStream *stream) { // Load in the character stats and active party Common::SeekableReadStream *chr = createReadStreamForMember("maze.chr"); Common::Serializer sChr(chr, nullptr); - _roster.synchronize(sChr); + _party._roster.synchronize(sChr); delete chr; Common::SeekableReadStream *pty = createReadStreamForMember("maze.pty"); @@ -158,7 +158,7 @@ void SavesManager::reset() { File fChar("maze.chr", gameCur); Common::Serializer sChar(&fChar, nullptr); - _roster.synchronize(sChar); + _party._roster.synchronize(sChar); fChar.close(); } diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h index 5d35518348..8f112f689e 100644 --- a/engines/xeen/saves.h +++ b/engines/xeen/saves.h @@ -59,7 +59,6 @@ class SavesManager: public BaseCCArchive { private: XeenEngine *_vm; Party &_party; - Roster &_roster; byte *_data; Common::HashMap<uint16, Common::MemoryWriteStreamDynamic > _newData; @@ -70,7 +69,7 @@ public: bool _wonWorld; bool _wonDarkSide; public: - SavesManager(XeenEngine *vm, Party &party, Roster &roster); + SavesManager(XeenEngine *vm, Party &party); ~SavesManager(); diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index ed944262e1..3c2b7a2c77 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -94,7 +94,7 @@ void XeenEngine::initialize() { _interface = new Interface(this); _map = new Map(this); _party = new Party(this); - _saves = new SavesManager(this, *_party, _roster); + _saves = new SavesManager(this, *_party); _screen = new Screen(this); _scripts = new Scripts(this); _screen->setupWindows(); diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 4664998a3e..c4f826d508 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -152,7 +152,6 @@ public: Mode _mode; GameEvent _gameEvent; Common::SeekableReadStream *_eventData; - Roster _roster; int _quitMode; bool _dangerSenseAllowed; bool _noDirectionSense; -- cgit v1.2.3 From a612dd686c27303bdbe6b2dba89aef79bc8db8e0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 9 Feb 2015 22:01:01 -0500 Subject: XEEN: Further refactoring for party dialog setup --- engines/xeen/dialogs_party.cpp | 36 +++++++++++++----------------------- engines/xeen/interface.cpp | 22 ---------------------- engines/xeen/interface.h | 4 ---- engines/xeen/party.cpp | 4 ++-- engines/xeen/party.h | 2 +- engines/xeen/screen.cpp | 16 ++++++++++++++++ engines/xeen/screen.h | 2 ++ 7 files changed, 34 insertions(+), 52 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index aa8d58f32b..3da4a2ae3a 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -40,6 +40,7 @@ void PartyDialog::execute() { Map &map = *_vm->_map; Party &party = *_vm->_party; Screen &screen = *_vm->_screen; + bool modeFlag = false; loadButtons(); setupBackground(); @@ -73,10 +74,7 @@ void PartyDialog::execute() { _iconSprites.draw(w, 10, Common::Point(192, 100)); screen.loadPalette("mm4.pal"); - /* - - - if (flag) { + if (modeFlag) { screen._windows[0].update(); events.setCursor(0); screen.fadeIn(4); @@ -94,7 +92,6 @@ void PartyDialog::execute() { } } - // TODO bool breakFlag = false; while (!_vm->shouldQuit() && !breakFlag) { events.pollEventsAndWait(); @@ -105,13 +102,13 @@ void PartyDialog::execute() { case Common::KEYCODE_SPACE: case Common::KEYCODE_e: case Common::KEYCODE_x: - if (_vm->_party->_partyCount == 0) { + if (party._partyCount == 0) { ErrorScroll::show(_vm, NO_ONE_TO_ADVENTURE_WITH); } else { if (_vm->_mode != MODE_0) { - for (_intrIndex1 = 4; _intrIndex1 >= 0; --_intrIndex1) { + for (int idx = 4; idx >= 0; --idx) { events.updateGameCounter(); - drawViewBackground(_intrIndex1); + screen.frameWindow(idx); w.update(); while (events.timeElapsed() < 1) @@ -120,10 +117,10 @@ void PartyDialog::execute() { } w.close(); - _vm->_party->_realPartyCount = _vm->_party->_partyCount; - _vm->_party->_mazeId = _vm->_party->_priorMazeId; + party._realPartyCount = party._partyCount; + party._mazeId = party._priorMazeId; - _vm->_party->copyPartyToRoster(_vm->_roster); + party.copyPartyToRoster(); _vm->_saves->writeCharFile(); breakFlag = true; break; @@ -143,18 +140,17 @@ void PartyDialog::execute() { } else { screen.fadeOut(4); w.close(); - moveCharacterToRoster(); + party.copyPartyToRoster(); _vm->_saves->writeCharFile(); screen.fadeOut(4); - flag = true; - _buttonsLoaded = true; - goto start; + modeFlag = true; + breakFlag = true; } break; case Common::KEYCODE_d: break; case Common::KEYCODE_r: - if (_vm->_party->_partyCount > 0) { + if (party._partyCount > 0) { // TODO } break; @@ -187,12 +183,6 @@ void PartyDialog::execute() { } } } - - for (int i = 0; i < TOTAL_CHARACTERS; ++i) - _charFaces[i].clear(); - */ - // TODO - } } void PartyDialog::loadButtons() { @@ -237,7 +227,7 @@ void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bo for (posIndex = 0; posIndex < 4; ++posIndex) { charId = xeenSideChars[charIndex]; - bool isInParty = _vm->_party->isInParty(charId); + bool isInParty = party.isInParty(charId); if (charId == 0xff) { while ((int)_buttons.size() >(7 + posIndex)) diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 8aa938b583..13a12f085a 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -85,7 +85,6 @@ void Interface::loadPartyIcons() { } void Interface::charIconsPrint(bool updateFlag) { - Resources &res = *_vm->_resources; Screen &screen = *_vm->_screen; bool stateFlag = _vm->_mode == MODE_COMBAT; _restoreSprites.draw(screen, 0, Common::Point(8, 149)); @@ -153,27 +152,6 @@ void Interface::sortFaces() { } } -void Interface::drawViewBackground(int bgType) { - if (bgType >= 4) - return; - - if (bgType == 0) { - // Totally black background - _vm->_screen->fillRect(Common::Rect(8, 8, 224, 140), 0); - } else { - const byte *lookup = BACKGROUND_XLAT + bgType; - for (int yp = 8; yp < 140; ++yp) { - byte *destP = (byte *)_vm->_screen->getBasePtr(8, yp); - for (int xp = 8; xp < 224; ++xp, ++destP) - *destP = lookup[*destP]; - } - } -} - -void Interface::moveCharacterToRoster() { - error("TODO"); -} - void Interface::startup() { Screen &screen = *_vm->_screen; _iconSprites.load("main.icn"); diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index cce2eaaa30..3d496aa2b1 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -57,10 +57,6 @@ private: void setupBackground(); - void drawViewBackground(int bgType); - - void moveCharacterToRoster(); - void setMainButtons(); void chargeStep(); diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 5cf5181142..6bff8fd995 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -231,9 +231,9 @@ bool Party::isInParty(int charId) { return false; } -void Party::copyPartyToRoster(Roster &r) { +void Party::copyPartyToRoster() { for (int i = 0; i < _partyCount; ++i) { - r[_partyMembers[i]] = _activeParty[i]; + _roster[_partyMembers[i]] = _activeParty[i]; } } diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 1382969477..c37a673ee5 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -138,7 +138,7 @@ public: bool isInParty(int charId); - void copyPartyToRoster(Roster &r); + void copyPartyToRoster(); void changeTime(int numMinutes); diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index bb2f356f1b..3b3ea6969b 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -481,5 +481,21 @@ void Screen::restoreBackground(int slot) { _savedScreens[slot - 1].blitTo(*this); } +void Screen::frameWindow(uint bgType) { + if (bgType >= 4) + return; + + if (bgType == 0) { + // Totally black background + _vm->_screen->fillRect(Common::Rect(8, 8, 224, 140), 0); + } else { + const byte *lookup = BACKGROUND_XLAT + bgType; + for (int yp = 8; yp < 140; ++yp) { + byte *destP = (byte *)_vm->_screen->getBasePtr(8, yp); + for (int xp = 8; xp < 224; ++xp, ++destP) + *destP = lookup[*destP]; + } + } +} } // End of namespace Xeen diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index e3ced06236..526fd6f845 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -156,6 +156,8 @@ public: void saveBackground(int slot = 1); void restoreBackground(int slot = 1); + + void frameWindow(uint bgType); }; } // End of namespace Xeen -- cgit v1.2.3 From 8256f7c8dfcdefe7da352fd36b42dc0931a111f8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 10 Feb 2015 08:42:59 -0500 Subject: XEEN: Refacored face sprites loading into Roster and Character classes --- engines/xeen/character.cpp | 2 + engines/xeen/character.h | 3 ++ engines/xeen/dialogs_dismiss.cpp | 1 - engines/xeen/dialogs_exchange.cpp | 1 - engines/xeen/dialogs_party.cpp | 83 +++++++++++++++++++++------------------ engines/xeen/dialogs_party.h | 5 ++- engines/xeen/interface.cpp | 23 +---------- engines/xeen/interface.h | 3 -- engines/xeen/party.cpp | 18 +++++++-- engines/xeen/party.h | 4 +- engines/xeen/resources.cpp | 6 --- engines/xeen/resources.h | 1 - engines/xeen/xeen.cpp | 1 - 13 files changed, 74 insertions(+), 77 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index fb1447d84c..dc193f45be 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -734,6 +734,8 @@ void Character::clear() { _armor.clear(); _accessories.clear(); _misc.clear(); + + _faceSprites = nullptr; } void Character::synchronize(Common::Serializer &s) { diff --git a/engines/xeen/character.h b/engines/xeen/character.h index 7fc13f1015..53dee33980 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -28,6 +28,7 @@ #include "common/rect.h" #include "common/serializer.h" #include "xeen/combat.h" +#include "xeen/sprites.h" namespace Xeen { @@ -257,6 +258,8 @@ public: uint32 _experience; int _currentAdventuringSpell; int _currentCombatSpell; + + SpriteResource *_faceSprites; public: Character(); diff --git a/engines/xeen/dialogs_dismiss.cpp b/engines/xeen/dialogs_dismiss.cpp index 304c7a0cef..c387c28019 100644 --- a/engines/xeen/dialogs_dismiss.cpp +++ b/engines/xeen/dialogs_dismiss.cpp @@ -72,7 +72,6 @@ void Dismiss::execute() { } else { Character tempChar = party._activeParty[_buttonValue]; int charIndex = party._partyMembers[_buttonValue]; - intf._partyFaces[_buttonValue] = 0; intf.sortFaces(); // party.sortParty(); diff --git a/engines/xeen/dialogs_exchange.cpp b/engines/xeen/dialogs_exchange.cpp index 56a310a928..c6a4522c88 100644 --- a/engines/xeen/dialogs_exchange.cpp +++ b/engines/xeen/dialogs_exchange.cpp @@ -54,7 +54,6 @@ void ExchangeDialog::execute(Character *&c, int &charIndex) { if (_buttonValue < party._partyCount) { SWAP(party._activeParty[charIndex], party._activeParty[_buttonValue]); SWAP(party._partyMembers[charIndex], party._partyMembers[_buttonValue]); - SWAP(intf._partyFaces[charIndex], intf._partyFaces[_buttonValue]); charIndex = _buttonValue; c = &party._activeParty[charIndex]; diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index 3da4a2ae3a..c8689f0656 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -21,6 +21,7 @@ */ #include "common/scummsys.h" +#include "xeen/dialogs_char_info.h" #include "xeen/dialogs_party.h" #include "xeen/character.h" #include "xeen/events.h" @@ -41,6 +42,7 @@ void PartyDialog::execute() { Party &party = *_vm->_party; Screen &screen = *_vm->_screen; bool modeFlag = false; + int startingChar = 0; loadButtons(); setupBackground(); @@ -62,7 +64,7 @@ void PartyDialog::execute() { Window &w = screen._windows[11]; w.open(); - setupFaces(0, xeenSideChars, false); + setupFaces(startingChar, xeenSideChars, false); w.writeString(_displayText); w.drawList(&_faceDrawStructs[0], 4); @@ -122,18 +124,30 @@ void PartyDialog::execute() { party.copyPartyToRoster(); _vm->_saves->writeCharFile(); - breakFlag = true; - break; + return; } break; - case Common::KEYCODE_1: + + case Common::KEYCODE_F1: + case Common::KEYCODE_F2: + case Common::KEYCODE_F3: + case Common::KEYCODE_F4: + case Common::KEYCODE_F5: + case Common::KEYCODE_F6: + // Show character info + _buttonValue -= Common::KEYCODE_F1; + if (_buttonValue < party._partyCount) + CharacterInfo::show(_vm, _buttonValue); break; + + case Common::KEYCODE_1: case Common::KEYCODE_2: - break; case Common::KEYCODE_3: - break; case Common::KEYCODE_4: + _buttonValue -= Common::KEYCODE_1 - 7; + // TODO break; + case Common::KEYCODE_c: if (xeenSideChars.size() == 24) { ErrorScroll::show(_vm, YOUR_ROSTER_IS_FULL); @@ -154,28 +168,17 @@ void PartyDialog::execute() { // TODO } break; - case 201: - // TODO - break; - case 202: - // TODO - break; - case 203: - // TODO - break; - case 204: - // TODO - break; - case 205: - // TODO - break; - case 206: - // TODO - break; - case 242: + + case Common::KEYCODE_UP: + case Common::KEYCODE_KP8: + if (startingChar > 0) { + startingChar -= 4; + startingCharChanged(xeenSideChars, startingChar); + } // TODO break; - case 243: + case Common::KEYCODE_DOWN: + case Common::KEYCODE_KP2: // TODO break; default: @@ -215,7 +218,7 @@ void PartyDialog::setupBackground() { /** * Sets up the faces for display in the party dialog */ -void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag) { +void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideChars, bool updateFlag) { Party &party = *_vm->_party; Resources &res = *_vm->_resources; Common::String charNames[4]; @@ -226,10 +229,11 @@ void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bo int charId; for (posIndex = 0; posIndex < 4; ++posIndex) { - charId = xeenSideChars[charIndex]; + charId = (firstDisplayChar + posIndex) >= xeenSideChars.size() ? -1 : + xeenSideChars[firstDisplayChar + posIndex]; bool isInParty = party.isInParty(charId); - if (charId == 0xff) { + if (charId == -1) { while ((int)_buttons.size() >(7 + posIndex)) _buttons.remove_at(_buttons.size() - 1); break; @@ -237,7 +241,7 @@ void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bo Common::Rect &b = _buttons[7 + posIndex]._bounds; b.moveTo((posIndex & 1) ? 117 : 16, b.top); - Character &ps = party._roster[xeenSideChars[charIndex + posIndex]]; + Character &ps = party._roster[xeenSideChars[firstDisplayChar + posIndex]]; charNames[posIndex] = isInParty ? IN_PARTY : ps._name; charRaces[posIndex] = RACE_NAMES[ps._race]; charSex[posIndex] = SEX_NAMES[ps._sex]; @@ -247,14 +251,12 @@ void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bo charIconsPrint(updateFlag); // Set up the sprite set to use for each face - charId = xeenSideChars[charIndex]; - _faceDrawStructs[0]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId]; - charId = xeenSideChars[charIndex + 1]; - _faceDrawStructs[1]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId]; - charId = xeenSideChars[charIndex + 2]; - _faceDrawStructs[2]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId]; - charId = xeenSideChars[charIndex + 3]; - _faceDrawStructs[3]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId]; + for (int posIndex = 0; posIndex < 4; ++posIndex) { + if ((firstDisplayChar + posIndex) >= xeenSideChars.size()) + _faceDrawStructs[posIndex]._sprites = nullptr; + else + _faceDrawStructs[posIndex]._sprites = party._roster[posIndex]._faceSprites; + } _displayText = Common::String::format(PARTY_DETAILS, charNames[0].c_str(), charRaces[0].c_str(), charSex[0].c_str(), charClasses[0].c_str(), @@ -264,4 +266,9 @@ void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bo ); } +void PartyDialog::startingCharChanged(Common::Array<int> &charList, int firstDisplayChar) { + Party &party = *_vm->_party; + +} + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h index c2768e9994..4450f3f6cd 100644 --- a/engines/xeen/dialogs_party.h +++ b/engines/xeen/dialogs_party.h @@ -23,6 +23,7 @@ #ifndef XEEN_DIALOGS_PARTY_H #define XEEN_DIALOGS_PARTY_H +#include "common/array.h" #include "xeen/dialogs.h" #include "xeen/screen.h" #include "xeen/sprites.h" @@ -48,7 +49,9 @@ private: void charIconsPrint(bool updateFlag); - void setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag); + void setupFaces(int firstDisplayChar, Common::Array<int> xeenSideChars, bool updateFlag); + + void startingCharChanged(Common::Array<int> &charList, int firstDisplayChar); public: static void show(XeenEngine *vm); }; diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 13a12f085a..15f19c57be 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -34,7 +34,6 @@ namespace Xeen { Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(vm) { - Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], (SpriteResource *)nullptr); _buttonsLoaded = false; _hiliteChar = -1; _intrIndex1 = 0; @@ -76,14 +75,6 @@ void Interface::setup() { party._newDay = party._minutes >= 300; } -void Interface::loadPartyIcons() { - Party &party = *_vm->_party; - Resources &res = *_vm->_resources; - - for (int i = 0; i < party._partyCount; ++i) - _partyFaces[i] = &res._charFaces[_vm->_party->_partyMembers[i]]; -} - void Interface::charIconsPrint(bool updateFlag) { Screen &screen = *_vm->_screen; bool stateFlag = _vm->_mode == MODE_COMBAT; @@ -97,7 +88,7 @@ void Interface::charIconsPrint(bool updateFlag) { Condition charCondition = ps.worstCondition(); int charFrame = FACE_CONDITION_FRAMES[charCondition]; - SpriteResource *sprites = (charFrame > 4) ? &_dseFace : _partyFaces[charIndex]; + SpriteResource *sprites = (charFrame > 4) ? &_dseFace : ps._faceSprites; if (charFrame > 4) charFrame -= 5; @@ -139,17 +130,7 @@ void Interface::charIconsPrint(bool updateFlag) { * Removes any empty character entries from the faces list */ void Interface::sortFaces() { - for (uint charIdx = 0; charIdx < MAX_ACTIVE_PARTY; ++charIdx) { - if (!_partyFaces[charIdx]) { - for (uint charIdx2 = charIdx + 1; charIdx2 < 8; ++charIdx2) { - if (_partyFaces[charIdx2]) { - _partyFaces[charIdx] = _partyFaces[charIdx2]; - _partyFaces[charIdx2] = 0; - break; - } - } - } - } + // No implementation needed } void Interface::startup() { diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 3d496aa2b1..7dc1b53170 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -69,7 +69,6 @@ private: public: int _intrIndex1; Common::String _interfaceText; - SpriteResource *_partyFaces[MAX_ACTIVE_PARTY]; public: Interface(XeenEngine *vm); @@ -79,8 +78,6 @@ public: void manageCharacters(bool soundPlayed); - void loadPartyIcons(); - void startup(); void mainIconsPrint(); diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 6bff8fd995..e0110856a6 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -32,10 +32,22 @@ namespace Xeen { -void Roster::synchronize(Common::Serializer &s) { - if (s.isLoading()) - resize(30); +Roster::Roster() { + resize(TOTAL_CHARACTERS); + + for (int idx = 0; idx < TOTAL_CHARACTERS; ++idx) { + if (idx < XEEN_TOTAL_CHARACTERS) { + // Load new character resource + Common::String name = Common::String::format("char%02d.fac", idx + 1); + _charFaces[idx].load(name); + operator[](idx)._faceSprites = &_charFaces[idx]; + } else { + operator[](idx)._faceSprites = nullptr; + } + } +} +void Roster::synchronize(Common::Serializer &s) { for (uint i = 0; i < 30; ++i) (*this)[i].synchronize(s); } diff --git a/engines/xeen/party.h b/engines/xeen/party.h index c37a673ee5..a91b398931 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -50,7 +50,9 @@ enum Difficulty { ADVENTURER = 0, WARRIOR = 1 }; class Roster: public Common::Array<Character> { public: - Roster() {} + SpriteResource _charFaces[TOTAL_CHARACTERS]; +public: + Roster(); void synchronize(Common::Serializer &s); }; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 7067886c87..11b209274d 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -31,12 +31,6 @@ Resources::Resources() { while (f.pos() < f.size()) _maeNames.push_back(f.readString()); f.close(); - - for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { - // Load new character resource - Common::String name = Common::String::format("char%02d.fac", i + 1); - _charFaces[i].load(name); - } } /*------------------------------------------------------------------------*/ diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index dd3a77504a..de99c984eb 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -35,7 +35,6 @@ class Resources { public: // Magic and equipment names Common::StringArray _maeNames; - SpriteResource _charFaces[TOTAL_CHARACTERS]; public: Resources(); }; diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 3c2b7a2c77..e0a2bebacd 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -295,7 +295,6 @@ void XeenEngine::play() { _interface->setup(); _screen->loadBackground("back.raw"); _screen->loadPalette("mm4.pal"); - _interface->loadPartyIcons(); if (getGameID() != GType_WorldOfXeen && !_map->_loadDarkSide) { _map->_loadDarkSide = true; -- cgit v1.2.3 From e59617834503da077c27c5dff37f620bb1e9f0c1 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 10 Feb 2015 19:28:45 -0500 Subject: XEEN: Refactored drawing the party icons into a separate class --- engines/xeen/dialogs_dismiss.cpp | 1 - engines/xeen/dialogs_exchange.cpp | 2 +- engines/xeen/dialogs_items.cpp | 2 +- engines/xeen/dialogs_party.cpp | 9 +- engines/xeen/dialogs_party.h | 2 +- engines/xeen/dialogs_query.cpp | 5 +- engines/xeen/interface.cpp | 193 +++++++++++++++++++------------------- engines/xeen/interface.h | 33 ++++--- engines/xeen/interface_map.cpp | 15 +-- engines/xeen/interface_map.h | 1 - engines/xeen/party.cpp | 4 +- engines/xeen/resources.cpp | 2 + engines/xeen/resources.h | 4 +- engines/xeen/scripts.cpp | 2 +- engines/xeen/town.cpp | 10 +- 15 files changed, 148 insertions(+), 137 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_dismiss.cpp b/engines/xeen/dialogs_dismiss.cpp index c387c28019..b512b66806 100644 --- a/engines/xeen/dialogs_dismiss.cpp +++ b/engines/xeen/dialogs_dismiss.cpp @@ -73,7 +73,6 @@ void Dismiss::execute() { Character tempChar = party._activeParty[_buttonValue]; int charIndex = party._partyMembers[_buttonValue]; - intf.sortFaces(); // party.sortParty(); // TODO diff --git a/engines/xeen/dialogs_exchange.cpp b/engines/xeen/dialogs_exchange.cpp index c6a4522c88..0418b4037c 100644 --- a/engines/xeen/dialogs_exchange.cpp +++ b/engines/xeen/dialogs_exchange.cpp @@ -65,7 +65,7 @@ void ExchangeDialog::execute(Character *&c, int &charIndex) { } w.close(); - intf.charIconsPrint(true); + intf.drawParty(true); intf.highlightChar(charIndex); } diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index 002a8fb946..7b4e23eb01 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -505,7 +505,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { } } - intf.charIconsPrint(true); + intf.drawParty(true); if (updateStock) charData2BlackData(); diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index c8689f0656..9202187b6a 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -220,7 +220,6 @@ void PartyDialog::setupBackground() { */ void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideChars, bool updateFlag) { Party &party = *_vm->_party; - Resources &res = *_vm->_resources; Common::String charNames[4]; Common::String charRaces[4]; Common::String charSex[4]; @@ -229,7 +228,7 @@ void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideCh int charId; for (posIndex = 0; posIndex < 4; ++posIndex) { - charId = (firstDisplayChar + posIndex) >= xeenSideChars.size() ? -1 : + charId = (firstDisplayChar + posIndex) >= (int)xeenSideChars.size() ? -1 : xeenSideChars[firstDisplayChar + posIndex]; bool isInParty = party.isInParty(charId); @@ -248,11 +247,11 @@ void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideCh charClasses[posIndex] = CLASS_NAMES[ps._class]; } - charIconsPrint(updateFlag); + drawParty(updateFlag); // Set up the sprite set to use for each face for (int posIndex = 0; posIndex < 4; ++posIndex) { - if ((firstDisplayChar + posIndex) >= xeenSideChars.size()) + if ((firstDisplayChar + posIndex) >= (int)xeenSideChars.size()) _faceDrawStructs[posIndex]._sprites = nullptr; else _faceDrawStructs[posIndex]._sprites = party._roster[posIndex]._faceSprites; @@ -268,7 +267,7 @@ void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideCh void PartyDialog::startingCharChanged(Common::Array<int> &charList, int firstDisplayChar) { Party &party = *_vm->_party; - + // TODO } } // End of namespace Xeen diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h index 4450f3f6cd..327c29953b 100644 --- a/engines/xeen/dialogs_party.h +++ b/engines/xeen/dialogs_party.h @@ -47,7 +47,7 @@ private: void setupBackground(); - void charIconsPrint(bool updateFlag); + void drawParty(bool updateFlag); void setupFaces(int firstDisplayChar, Common::Array<int> xeenSideChars, bool updateFlag); diff --git a/engines/xeen/dialogs_query.cpp b/engines/xeen/dialogs_query.cpp index f226521a94..c982b8acd2 100644 --- a/engines/xeen/dialogs_query.cpp +++ b/engines/xeen/dialogs_query.cpp @@ -97,11 +97,12 @@ bool YesNo::show(XeenEngine *vm, bool type, bool townFlag) { } bool YesNo::execute(bool type, bool townFlag) { - Screen &screen = *_vm->_screen; EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; Map &map = *_vm->_map; Party &party = *_vm->_party; + Resources &res = *_vm->_resources; + Screen &screen = *_vm->_screen; Town &town = *_vm->_town; SpriteResource confirmSprites; int numFrames; @@ -112,7 +113,7 @@ bool YesNo::execute(bool type, bool townFlag) { if (!type) { confirmSprites.load("confirm.icn"); - intf._globalSprites.draw(screen, 7, Common::Point(232, 74)); + res._globalSprites.draw(screen, 7, Common::Point(232, 74)); confirmSprites.draw(screen, 0, Common::Point(235, 75)); confirmSprites.draw(screen, 2, Common::Point(260, 75)); screen._windows[34].update(); diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 15f19c57be..7c9e8a323a 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -33,9 +33,96 @@ namespace Xeen { -Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(vm) { - _buttonsLoaded = false; +PartyDrawer::PartyDrawer(XeenEngine *vm): _vm(vm) { + _restoreSprites.load("restorex.icn"); + _hpSprites.load("hpbars.icn"); + _dseFace.load("dse.fac"); _hiliteChar = -1; +} + +void PartyDrawer::drawParty(bool updateFlag) { + Party &party = *_vm->_party; + Resources &res = *_vm->_resources; + Screen &screen = *_vm->_screen; + bool inCombat = _vm->_mode == MODE_COMBAT; + _restoreSprites.draw(screen, 0, Common::Point(8, 149)); + + // Handle drawing the party faces + uint partyCount = inCombat ? party._combatParty.size() : party._activeParty.size(); + for (uint idx = 0; idx < partyCount; ++idx) { + Character &ps = inCombat ? *party._combatParty[idx] : party._activeParty[idx]; + Condition charCondition = ps.worstCondition(); + int charFrame = FACE_CONDITION_FRAMES[charCondition]; + + SpriteResource *sprites = (charFrame > 4) ? &_dseFace : ps._faceSprites; + if (charFrame > 4) + charFrame -= 5; + + sprites->draw(screen, charFrame, Common::Point(CHAR_FACES_X[idx], 150)); + } + + for (uint idx = 0; idx < partyCount; ++idx) { + Character &ps = inCombat ? *party._combatParty[idx] : party._activeParty[idx]; + + // Draw the Hp bar + int maxHp = ps.getMaxHP(); + int frame; + if (ps._currentHp < 1) + frame = 4; + else if (ps._currentHp > maxHp) + frame = 3; + else if (ps._currentHp == maxHp) + frame = 0; + else if (ps._currentHp < (maxHp / 4)) + frame = 2; + else + frame = 1; + + _hpSprites.draw(screen, frame, Common::Point(HP_BARS_X[idx], 182)); + } + + if (_hiliteChar != -1) + res._globalSprites.draw(screen, 8, Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149)); + + if (updateFlag) + screen._windows[33].update(); +} + +void PartyDrawer::highlightChar(int charId) { + Resources &res = *_vm->_resources; + Screen &screen = *_vm->_screen; + + if (charId != _hiliteChar && _hiliteChar != HILIGHT_CHAR_DISABLED) { + // Handle deselecting any previusly selected char + if (_hiliteChar != -1) { + res._globalSprites.draw(screen, 9 + _hiliteChar, + Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149)); + } + + // Highlight new character + res._globalSprites.draw(screen, 8, Common::Point(CHAR_FACES_X[charId] - 1, 149)); + _hiliteChar = charId; + screen._windows[33].update(); + } +} + +void PartyDrawer::unhighlightChar() { + Resources &res = *_vm->_resources; + Screen &screen = *_vm->_screen; + + if (_hiliteChar != -1) { + res._globalSprites.draw(screen, _hiliteChar + 9, + Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149)); + _hiliteChar = -1; + screen._windows[33].update(); + } +} + +/*------------------------------------------------------------------------*/ + +Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), + PartyDrawer(vm), _vm(vm) { + _buttonsLoaded = false; _intrIndex1 = 0; _steppingFX = 0; @@ -65,75 +152,15 @@ void Interface::initDrawStructs() { void Interface::setup() { InterfaceMap::setup(); - _restoreSprites.load("restorex.icn"); - _hpSprites.load("hpbars.icn"); _uiSprites.load("inn.icn"); - _dseFace.load("dse.fac"); Party &party = *_vm->_party; party.loadActiveParty(); party._newDay = party._minutes >= 300; } -void Interface::charIconsPrint(bool updateFlag) { - Screen &screen = *_vm->_screen; - bool stateFlag = _vm->_mode == MODE_COMBAT; - _restoreSprites.draw(screen, 0, Common::Point(8, 149)); - - // Handle drawing the party faces - for (int idx = 0; idx < (stateFlag ? _vm->_party->_combatPartyCount : - _vm->_party->_partyCount); ++idx) { - int charIndex = stateFlag ? _combatCharIds[idx] : idx; - Character &ps = _vm->_party->_activeParty[charIndex]; - Condition charCondition = ps.worstCondition(); - int charFrame = FACE_CONDITION_FRAMES[charCondition]; - - SpriteResource *sprites = (charFrame > 4) ? &_dseFace : ps._faceSprites; - if (charFrame > 4) - charFrame -= 5; - - sprites->draw(screen, charFrame, Common::Point(CHAR_FACES_X[idx], 150)); - } - - if (!_hpSprites.empty()) { - for (int idx = 0; idx < (stateFlag ? _vm->_party->_combatPartyCount : - _vm->_party->_partyCount); ++idx) { - int charIndex = stateFlag ? _combatCharIds[idx] : idx; - Character &ps = _vm->_party->_activeParty[charIndex]; - - // Draw the Hp bar - int maxHp = ps.getMaxHP(); - int frame; - if (ps._currentHp < 1) - frame = 4; - else if (ps._currentHp > maxHp) - frame = 3; - else if (ps._currentHp == maxHp) - frame = 0; - else if (ps._currentHp < (maxHp / 4)) - frame = 2; - else - frame = 1; - - _hpSprites.draw(screen, frame, Common::Point(HP_BARS_X[idx], 182)); - } - } - - if (_hiliteChar != -1) - _globalSprites.draw(screen, 8, Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149)); - - if (updateFlag) - screen._windows[33].update(); -} - -/** - * Removes any empty character entries from the faces list - */ -void Interface::sortFaces() { - // No implementation needed -} - void Interface::startup() { + Resources &res = *_vm->_resources; Screen &screen = *_vm->_screen; _iconSprites.load("main.icn"); @@ -147,10 +174,10 @@ void Interface::startup() { } draw3d(false); - _globalSprites.draw(screen._windows[1], 5, Common::Point(232, 9)); - charIconsPrint(false); + res._globalSprites.draw(screen._windows[1], 5, Common::Point(232, 9)); + drawParty(false); - _mainList[0]._sprites = &_globalSprites; + _mainList[0]._sprites = &res._globalSprites; for (int i = 1; i < 16; ++i) _mainList[i]._sprites = &_iconSprites; @@ -582,34 +609,6 @@ void Interface::doFalling() { // TODO } -void Interface::highlightChar(int charId) { - Screen &screen = *_vm->_screen; - - if (charId != _hiliteChar && _hiliteChar != HILIGHT_CHAR_DISABLED) { - // Handle deselecting any previusly selected char - if (_hiliteChar != -1) { - _globalSprites.draw(screen, 9 + _hiliteChar, - Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149)); - } - - // Highlight new character - _globalSprites.draw(screen, 8, Common::Point(CHAR_FACES_X[charId] - 1, 149)); - _hiliteChar = charId; - screen._windows[33].update(); - } -} - -void Interface::unhighlightChar() { - Screen &screen = *_vm->_screen; - - if (_hiliteChar != -1) { - _globalSprites.draw(screen, _hiliteChar + 9, - Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149)); - _hiliteChar = -1; - screen._windows[33].update(); - } -} - bool Interface::checkMoveDirection(int key) { Map &map = *_vm->_map; Party &party = *_vm->_party; @@ -738,7 +737,7 @@ void Interface::rest() { for (uint charIdx = 0; charIdx < party._activeParty.size(); ++charIdx) { party._activeParty[charIdx]._conditions[ASLEEP] = 1; } - charIconsPrint(true); + drawParty(true); Mode oldMode = _vm->_mode; _vm->_mode = MODE_SLEEPING; @@ -826,7 +825,7 @@ void Interface::rest() { } } - charIconsPrint(true); + drawParty(true); _vm->_mode = oldMode; doStepCode(); draw3d(true); @@ -924,7 +923,7 @@ void Interface::bash(const Common::Point &pt, Direction direction) { party.checkPartyDead(); events.ipause(2); - charIconsPrint(true); + drawParty(true); } diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 7dc1b53170..59801757be 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -36,19 +36,38 @@ class XeenEngine; #define MINIMAP_SIZE 7 #define HILIGHT_CHAR_DISABLED -2 -class Interface: public ButtonContainer, public InterfaceMap { +/** + * Class responsible for drawing the images of the characters in the party + */ +class PartyDrawer { private: XeenEngine *_vm; - SpriteResource _restoreSprites; SpriteResource _dseFace; SpriteResource _hpSprites; + SpriteResource _restoreSprites; + int _hiliteChar; +public: + PartyDrawer(XeenEngine *vm); + + void drawParty(bool updateFlag); + + void highlightChar(int charId); + + void unhighlightChar(); +}; + +/** + * Implements the main in-game interface + */ +class Interface: public ButtonContainer, public InterfaceMap, public PartyDrawer { +private: + XeenEngine *_vm; SpriteResource _uiSprites; SpriteResource _iconSprites; DrawStruct _mainList[16]; int _combatCharIds[8]; bool _buttonsLoaded; - int _hiliteChar; int _steppingFX; void initDrawStructs(); @@ -82,16 +101,8 @@ public: void mainIconsPrint(); - void charIconsPrint(bool updateFlag); - - void sortFaces(); - void doFalling(); - void highlightChar(int charId); - - void unhighlightChar(); - void perform(); void rest(); diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 42c5ff4e07..beaf241f40 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -399,7 +399,6 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) { } void InterfaceMap::setup() { - _globalSprites.load("global.icn"); _borderSprites.load("border.icn"); _spellFxSprites.load("spellfx.icn"); _fecpSprites.load("fecp.brd"); @@ -4490,10 +4489,11 @@ void InterfaceMap::moveMonsters() { } void InterfaceMap::assembleBorder() { + Resources &res = *_vm->_resources; Screen &screen = *_vm->_screen; // Draw the outer frame - _globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8)); + res._globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8)); // Draw the animating bat character used to show when levitate is active _borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16, @@ -4600,6 +4600,7 @@ void InterfaceMap::assembleBorder() { void InterfaceMap::drawMiniMap() { Map &map = *_vm->_map; Party &party = *_vm->_party; + Resources &res = *_vm->_resources; Screen &screen = *_vm->_screen; Window &window1 = screen._windows[1]; @@ -4607,7 +4608,7 @@ void InterfaceMap::drawMiniMap() { return; if (!party._automapOn && !party._wizardEyeActive) { // Draw the Might & Magic logo - _globalSprites.draw(window1, 5, Common::Point(232, 9)); + res._globalSprites.draw(window1, 5, Common::Point(232, 9)); return; } @@ -4618,7 +4619,7 @@ void InterfaceMap::drawMiniMap() { party._wizardEyeActive = false; if (map._isOutdoors) { - _globalSprites.draw(window1, 15, Common::Point(237, 12)); + res._globalSprites.draw(window1, 15, Common::Point(237, 12)); for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { @@ -4659,7 +4660,7 @@ void InterfaceMap::drawMiniMap() { } // Draw the direction arrow - _globalSprites.draw(window1, party._mazeDirection + 1, + res._globalSprites.draw(window1, party._mazeDirection + 1, Common::Point(267, 36)); } else { frame2 = (frame2 + 2) % 8; @@ -4844,7 +4845,7 @@ void InterfaceMap::drawMiniMap() { ++colNum, ++xDiff, xp += 10) { if (colNum == 4 && rowNum == 4) { // Center of the minimap. Draw the direction arrow - _globalSprites.draw(window1, party._mazeDirection + 1, + res._globalSprites.draw(window1, party._mazeDirection + 1, Common::Point(272, 40)); } @@ -4968,7 +4969,7 @@ void InterfaceMap::drawMiniMap() { } // Draw outer rectangle around the automap - _globalSprites.draw(window1, 6, Common::Point(223, 3)); + res._globalSprites.draw(window1, 6, Common::Point(223, 3)); party._wizardEyeActive = eyeActive; } diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 034d1a6746..660213a98e 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -130,7 +130,6 @@ public: OutdoorDrawList _outdoorList; IndoorDrawList _indoorList; SpriteResource _charPowSprites; - SpriteResource _globalSprites; bool _upDoorText; Common::String _screenText; int _face1State, _face2State; diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index e0110856a6..f14a0bfb1a 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -349,7 +349,7 @@ void Party::changeTime(int numMinutes) { } if (killed) - _vm->_interface->charIconsPrint(true); + _vm->_interface->drawParty(true); if (_isNight != (_minutes < (5 * 60) || _minutes >= (21 * 60))) _vm->_map->loadSky(); @@ -391,7 +391,7 @@ void Party::addTime(int numMinutes) { ErrorScroll::show(_vm, THE_PARTY_NEEDS_REST, WT_NONFREEZED_WAIT); } - _vm->_interface->charIconsPrint(true); + _vm->_interface->drawParty(true); } _newDay = false; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 11b209274d..e9178505ad 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -27,6 +27,8 @@ namespace Xeen { Resources::Resources() { + _globalSprites.load("global.icn"); + File f("mae.xen"); while (f.pos() < f.size()) _maeNames.push_back(f.readString()); diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index de99c984eb..d4e1c11694 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -33,8 +33,8 @@ namespace Xeen { class Resources { public: - // Magic and equipment names - Common::StringArray _maeNames; + SpriteResource _globalSprites; + Common::StringArray _maeNames; // Magic and equipment names public: Resources(); }; diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 3837509760..7ced6afa3f 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -174,7 +174,7 @@ int Scripts::checkEvents() { intf._face1State = intf._face2State = 2; if (_refreshIcons) { screen.closeWindows(); - intf.charIconsPrint(true); + intf.drawParty(true); } // TODO diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index c12973cbcd..25f332a010 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -621,7 +621,7 @@ Character *Town::doTavernOptions(Character *c) { if (_vm->getRandomNumber(100) < 26) { ++c->_conditions[DRUNK]; - intf.charIconsPrint(true); + intf.drawParty(true); sound.playFX(28); } @@ -823,7 +823,7 @@ Character *Town::doTempleOptions(Character *c) { party._powerShield = amt; party._blessed = amt; - intf.charIconsPrint(true); + intf.drawParty(true); sound.playSample(nullptr, 0); File f("ahh.voc"); sound.playSample(&f, 1); @@ -854,7 +854,7 @@ Character *Town::doTempleOptions(Character *c) { Common::fill(&c->_conditions[HEART_BROKEN], &c->_conditions[NO_CONDITION], 0); _v1 = 1440; - intf.charIconsPrint(true); + intf.drawParty(true); sound.playSample(nullptr, 0); File f("ahh.voc"); sound.playSample(&f, 1); @@ -871,7 +871,7 @@ Character *Town::doTempleOptions(Character *c) { } _v1 = 1440; - intf.charIconsPrint(true); + intf.drawParty(true); sound.playSample(nullptr, 0); File f("ahh.voc"); sound.playSample(&f, 1); @@ -941,7 +941,7 @@ Character *Town::doTrainingOptions(Character *c) { party.resetTemps(); c->_currentHp = c->getMaxHP(); c->_currentSp = c->getMaxSP(); - intf.charIconsPrint(true); + intf.drawParty(true); } } break; -- cgit v1.2.3 From 50ae4f95229e9a11b86884aa1fa1dffb6cfdc7a8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 10 Feb 2015 23:40:45 -0500 Subject: XEEN: Refactored _partyCount and _partyMembers into the _activeParty array --- engines/xeen/character.cpp | 4 +- engines/xeen/character.h | 1 + engines/xeen/dialogs.cpp | 1 + engines/xeen/dialogs_char_info.cpp | 4 +- engines/xeen/dialogs_dismiss.cpp | 2 +- engines/xeen/dialogs_exchange.cpp | 3 +- engines/xeen/dialogs_party.cpp | 213 ++++++++++++++++++++++++++++--------- engines/xeen/dialogs_party.h | 16 ++- engines/xeen/dialogs_quick_ref.cpp | 4 +- engines/xeen/dialogs_spells.cpp | 2 +- engines/xeen/dialogs_whowill.cpp | 6 +- engines/xeen/interface.cpp | 2 +- engines/xeen/interface_map.cpp | 8 +- engines/xeen/party.cpp | 54 ++++++---- engines/xeen/party.h | 4 +- engines/xeen/resources.cpp | 6 ++ engines/xeen/resources.h | 5 + engines/xeen/scripts.cpp | 10 +- engines/xeen/town.cpp | 24 ++--- 19 files changed, 256 insertions(+), 113 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index dc193f45be..e7b5d23ecc 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -689,6 +689,8 @@ Character::Character(): _weapons(this), _armor(this), _accessories(this), _misc(this), _items(_weapons, _armor, _accessories, _misc) { clear(); + _faceSprites = nullptr; + _rosterId = -1; } void Character::clear() { @@ -734,8 +736,6 @@ void Character::clear() { _armor.clear(); _accessories.clear(); _misc.clear(); - - _faceSprites = nullptr; } void Character::synchronize(Common::Serializer &s) { diff --git a/engines/xeen/character.h b/engines/xeen/character.h index 53dee33980..59f4ba65b6 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -260,6 +260,7 @@ public: int _currentCombatSpell; SpriteResource *_faceSprites; + int _rosterId; public: Character(); diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index b25a8e13c0..ff4eaf622a 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -33,6 +33,7 @@ namespace Xeen { */ void ButtonContainer::saveButtons() { _savedButtons.push(_buttons); + clearButtons(); } /* diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp index 36ca5bdd4c..de16e9559e 100644 --- a/engines/xeen/dialogs_char_info.cpp +++ b/engines/xeen/dialogs_char_info.cpp @@ -282,7 +282,7 @@ void CharacterInfo::addButtons() { Common::String CharacterInfo::loadCharacterDetails(const Character &c) { Condition condition = c.worstCondition(); Party &party = *_vm->_party; - int foodVal = party._food / party._partyCount / 3; + int foodVal = party._food / party._activeParty.size() / 3; int totalResist = c._fireResistence._permanent + c.itemScan(11) + c._fireResistence._temporary + @@ -498,7 +498,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) { case 18: { // Food - int food = (party._food / party._partyCount) / 3; + int food = (party._food / party._activeParty.size()) / 3; msg = Common::String::format(FOOD_TEXT, STAT_NAMES[attrib], party._food, food, food != 1 ? "s" : ""); break; diff --git a/engines/xeen/dialogs_dismiss.cpp b/engines/xeen/dialogs_dismiss.cpp index b512b66806..0c28affa6c 100644 --- a/engines/xeen/dialogs_dismiss.cpp +++ b/engines/xeen/dialogs_dismiss.cpp @@ -71,7 +71,7 @@ void Dismiss::execute() { w.open(); } else { Character tempChar = party._activeParty[_buttonValue]; - int charIndex = party._partyMembers[_buttonValue]; + int charIndex = party._activeParty[_buttonValue]._rosterId; // party.sortParty(); diff --git a/engines/xeen/dialogs_exchange.cpp b/engines/xeen/dialogs_exchange.cpp index 0418b4037c..0b1e538b38 100644 --- a/engines/xeen/dialogs_exchange.cpp +++ b/engines/xeen/dialogs_exchange.cpp @@ -51,9 +51,8 @@ void ExchangeDialog::execute(Character *&c, int &charIndex) { if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) { _buttonValue -= Common::KEYCODE_F1; - if (_buttonValue < party._partyCount) { + if (_buttonValue < (int)party._activeParty.size()) { SWAP(party._activeParty[charIndex], party._activeParty[_buttonValue]); - SWAP(party._partyMembers[charIndex], party._partyMembers[_buttonValue]); charIndex = _buttonValue; c = &party._activeParty[charIndex]; diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index 9202187b6a..618d29781d 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -30,7 +30,11 @@ namespace Xeen { - void PartyDialog::show(XeenEngine *vm) { +PartyDialog::PartyDialog(XeenEngine *vm) : ButtonContainer(), + PartyDrawer(vm), _vm(vm) { +} + +void PartyDialog::show(XeenEngine *vm) { PartyDialog *dlg = new PartyDialog(vm); dlg->execute(); delete dlg; @@ -41,6 +45,7 @@ void PartyDialog::execute() { Map &map = *_vm->_map; Party &party = *_vm->_party; Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; bool modeFlag = false; int startingChar = 0; @@ -49,31 +54,29 @@ void PartyDialog::execute() { while (!_vm->shouldQuit()) { _vm->_mode = MODE_1; - Common::Array<int> xeenSideChars; - - party.loadActiveParty(); // Build up a list of characters on the same Xeen side being loaded + _charList.clear(); for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { Character &player = party._roster[i]; if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0)) continue; - xeenSideChars.push_back(i); + _charList.push_back(i); } Window &w = screen._windows[11]; w.open(); - setupFaces(startingChar, xeenSideChars, false); + setupFaces(startingChar, false); w.writeString(_displayText); w.drawList(&_faceDrawStructs[0], 4); - _iconSprites.draw(w, 0, Common::Point(16, 100)); - _iconSprites.draw(w, 2, Common::Point(52, 100)); - _iconSprites.draw(w, 4, Common::Point(87, 100)); - _iconSprites.draw(w, 6, Common::Point(122, 100)); - _iconSprites.draw(w, 8, Common::Point(157, 100)); - _iconSprites.draw(w, 10, Common::Point(192, 100)); + _uiSprites.draw(w, 0, Common::Point(16, 100)); + _uiSprites.draw(w, 2, Common::Point(52, 100)); + _uiSprites.draw(w, 4, Common::Point(87, 100)); + _uiSprites.draw(w, 6, Common::Point(122, 100)); + _uiSprites.draw(w, 8, Common::Point(157, 100)); + _uiSprites.draw(w, 10, Common::Point(192, 100)); screen.loadPalette("mm4.pal"); if (modeFlag) { @@ -104,7 +107,7 @@ void PartyDialog::execute() { case Common::KEYCODE_SPACE: case Common::KEYCODE_e: case Common::KEYCODE_x: - if (party._partyCount == 0) { + if (party._activeParty.size() == 0) { ErrorScroll::show(_vm, NO_ONE_TO_ADVENTURE_WITH); } else { if (_vm->_mode != MODE_0) { @@ -119,7 +122,6 @@ void PartyDialog::execute() { } w.close(); - party._realPartyCount = party._partyCount; party._mazeId = party._priorMazeId; party.copyPartyToRoster(); @@ -136,7 +138,7 @@ void PartyDialog::execute() { case Common::KEYCODE_F6: // Show character info _buttonValue -= Common::KEYCODE_F1; - if (_buttonValue < party._partyCount) + if (_buttonValue < (int)party._activeParty.size()) CharacterInfo::show(_vm, _buttonValue); break; @@ -145,15 +147,49 @@ void PartyDialog::execute() { case Common::KEYCODE_3: case Common::KEYCODE_4: _buttonValue -= Common::KEYCODE_1 - 7; + if ((_buttonValue - 7 + startingChar) < (int)_charList.size()) { + // Check if the selected character is already in the party + uint idx = 0; + for (; idx < party._activeParty.size(); ++idx) { + if (_charList[_buttonValue - 7 + startingChar] == + party._activeParty[idx]._rosterId) + break; + } + + if (idx == party._activeParty.size()) { + sound.playFX(21); + ErrorScroll::show(_vm, YOUR_PARTY_IS_FULL); + } else { + party._activeParty.push_back(party._roster[ + _charList[_buttonValue - 7 + startingChar]]); + error("TODO"); + } + } + // TODO + break; + + case Common::KEYCODE_UP: + case Common::KEYCODE_KP8: + if (startingChar > 0) { + startingChar -= 4; + startingCharChanged(startingChar); + } + break; + case Common::KEYCODE_DOWN: + case Common::KEYCODE_KP2: // TODO break; case Common::KEYCODE_c: - if (xeenSideChars.size() == 24) { + // Create + if (_charList.size() == XEEN_TOTAL_CHARACTERS) { ErrorScroll::show(_vm, YOUR_ROSTER_IS_FULL); } else { screen.fadeOut(4); w.close(); + + createChar(); + party.copyPartyToRoster(); _vm->_saves->writeCharFile(); screen.fadeOut(4); @@ -162,25 +198,20 @@ void PartyDialog::execute() { } break; case Common::KEYCODE_d: + // Delete character break; case Common::KEYCODE_r: - if (party._partyCount > 0) { - // TODO - } - break; - - case Common::KEYCODE_UP: - case Common::KEYCODE_KP8: - if (startingChar > 0) { - startingChar -= 4; - startingCharChanged(xeenSideChars, startingChar); + // Remove character + if (party._activeParty.size() > 0) { + int charButtonValue = selectCharacter(false, startingChar); + if (charButtonValue != 0) { + party.copyPartyToRoster(); + party._activeParty.remove_at(charButtonValue - Common::KEYCODE_F1); + } + startingCharChanged(startingChar); } - // TODO - break; - case Common::KEYCODE_DOWN: - case Common::KEYCODE_KP2: - // TODO break; + default: break; } @@ -189,18 +220,18 @@ void PartyDialog::execute() { } void PartyDialog::loadButtons() { - _iconSprites.load("inn.icn"); - addButton(Common::Rect(16, 100, 40, 120), Common::KEYCODE_UP, &_iconSprites); - addButton(Common::Rect(52, 100, 76, 120), Common::KEYCODE_DOWN, &_iconSprites); - addButton(Common::Rect(87, 100, 111, 120), Common::KEYCODE_d, &_iconSprites); - addButton(Common::Rect(122, 100, 146, 120), Common::KEYCODE_r, &_iconSprites); - addButton(Common::Rect(157, 100, 181, 120), Common::KEYCODE_c, &_iconSprites); - addButton(Common::Rect(192, 100, 116, 120), Common::KEYCODE_x, &_iconSprites); - addButton(Common::Rect(0, 0, 0, 0), Common::KEYCODE_ESCAPE, &_iconSprites, false); - addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_iconSprites, false); - addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_iconSprites, false); - addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3, &_iconSprites, false); - addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4, &_iconSprites, false); + _uiSprites.load("inn.icn"); + addButton(Common::Rect(16, 100, 40, 120), Common::KEYCODE_UP, &_uiSprites); + addButton(Common::Rect(52, 100, 76, 120), Common::KEYCODE_DOWN, &_uiSprites); + addButton(Common::Rect(87, 100, 111, 120), Common::KEYCODE_d, &_uiSprites); + addButton(Common::Rect(122, 100, 146, 120), Common::KEYCODE_r, &_uiSprites); + addButton(Common::Rect(157, 100, 181, 120), Common::KEYCODE_c, &_uiSprites); + addButton(Common::Rect(192, 100, 116, 120), Common::KEYCODE_x, &_uiSprites); + addButton(Common::Rect(0, 0, 0, 0), Common::KEYCODE_ESCAPE, &_uiSprites, false); + addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_uiSprites, false); + addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_uiSprites, false); + addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3, &_uiSprites, false); + addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4, &_uiSprites, false); } void PartyDialog::initDrawStructs() { @@ -218,7 +249,7 @@ void PartyDialog::setupBackground() { /** * Sets up the faces for display in the party dialog */ -void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideChars, bool updateFlag) { +void PartyDialog::setupFaces(int firstDisplayChar, bool updateFlag) { Party &party = *_vm->_party; Common::String charNames[4]; Common::String charRaces[4]; @@ -228,8 +259,8 @@ void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideCh int charId; for (posIndex = 0; posIndex < 4; ++posIndex) { - charId = (firstDisplayChar + posIndex) >= (int)xeenSideChars.size() ? -1 : - xeenSideChars[firstDisplayChar + posIndex]; + charId = (firstDisplayChar + posIndex) >= (int)_charList.size() ? -1 : + _charList[firstDisplayChar + posIndex]; bool isInParty = party.isInParty(charId); if (charId == -1) { @@ -240,7 +271,7 @@ void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideCh Common::Rect &b = _buttons[7 + posIndex]._bounds; b.moveTo((posIndex & 1) ? 117 : 16, b.top); - Character &ps = party._roster[xeenSideChars[firstDisplayChar + posIndex]]; + Character &ps = party._roster[_charList[firstDisplayChar + posIndex]]; charNames[posIndex] = isInParty ? IN_PARTY : ps._name; charRaces[posIndex] = RACE_NAMES[ps._race]; charSex[posIndex] = SEX_NAMES[ps._sex]; @@ -251,7 +282,7 @@ void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideCh // Set up the sprite set to use for each face for (int posIndex = 0; posIndex < 4; ++posIndex) { - if ((firstDisplayChar + posIndex) >= (int)xeenSideChars.size()) + if ((firstDisplayChar + posIndex) >= (int)_charList.size()) _faceDrawStructs[posIndex]._sprites = nullptr; else _faceDrawStructs[posIndex]._sprites = party._roster[posIndex]._faceSprites; @@ -265,9 +296,91 @@ void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideCh ); } -void PartyDialog::startingCharChanged(Common::Array<int> &charList, int firstDisplayChar) { +void PartyDialog::startingCharChanged(int firstDisplayChar) { + Window &w = _vm->_screen->_windows[11]; + + setupFaces(firstDisplayChar, true); + w.writeString(_displayText); + w.drawList(_faceDrawStructs, 4); + + _uiSprites.draw(w, 0, Common::Point(16, 100)); + _uiSprites.draw(w, 2, Common::Point(52, 100)); + _uiSprites.draw(w, 4, Common::Point(87, 100)); + _uiSprites.draw(w, 6, Common::Point(122, 100)); + _uiSprites.draw(w, 8, Common::Point(157, 100)); + _uiSprites.draw(w, 10, Common::Point(192, 100)); + + w.update(); +} + +void PartyDialog::createChar() { + error("TODO: createChar"); +} + +int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) { + EventsManager &events = *_vm->_events; Party &party = *_vm->_party; - // TODO + Screen &screen = *_vm->_screen; + Window &w = screen._windows[28]; + + SpriteResource iconSprites; + iconSprites.load("esc.icn"); + + w.setBounds(Common::Rect(50, isDelete ? 112 : 76, 266, isDelete ? 148 : 112)); + w.open(); + w.writeString(Common::String::format(REMOVE_OR_DELETE_WHICH, + REMOVE_DELETE[isDelete ? 1 : 0])); + iconSprites.draw(w, 0, Common::Point(225, isDelete ? 120 : 84)); + w.update(); + + saveButtons(); + addButton(Common::Rect(225, isDelete ? 120 : 84, 249, isDelete ? 140 : 104), + Common::KEYCODE_ESCAPE, &iconSprites); + addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &iconSprites, false); + addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &iconSprites, false); + addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3, &iconSprites, false); + addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4, &iconSprites, false); + + int result = -1, v; + while (!_vm->shouldQuit() && result == -1) { + _buttonValue = 0; + while (!_vm->shouldQuit() && !_buttonValue) { + events.pollEventsAndWait(); + checkEvents(_vm); + } + + switch (_buttonValue) { + case Common::KEYCODE_ESCAPE: + result = 0; + break; + + case Common::KEYCODE_F1: + case Common::KEYCODE_F2: + case Common::KEYCODE_F3: + case Common::KEYCODE_F4: + case Common::KEYCODE_F5: + case Common::KEYCODE_F6: + v = _buttonValue - Common::KEYCODE_F1; + if (v < (int)party._activeParty.size()) + result = _buttonValue; + break; + + case Common::KEYCODE_1: + case Common::KEYCODE_2: + case Common::KEYCODE_3: + case Common::KEYCODE_4: + v = _buttonValue - Common::KEYCODE_1; + if ((firstDisplayChar + v) < (int)_charList.size()) + result = _buttonValue; + + default: + break; + } + } + + w.close(); + restoreButtons(); + return result == -1 ? 0 : result; } } // End of namespace Xeen diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h index 327c29953b..082c43bb22 100644 --- a/engines/xeen/dialogs_party.h +++ b/engines/xeen/dialogs_party.h @@ -25,19 +25,21 @@ #include "common/array.h" #include "xeen/dialogs.h" +#include "xeen/interface.h" #include "xeen/screen.h" #include "xeen/sprites.h" namespace Xeen { -class PartyDialog : public ButtonContainer { +class PartyDialog : public ButtonContainer, public PartyDrawer { private: XeenEngine *_vm; - SpriteResource _iconSprites; + SpriteResource _uiSprites; DrawStruct _faceDrawStructs[4]; Common::String _displayText; + Common::Array<int> _charList; - PartyDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + PartyDialog(XeenEngine *vm); void execute(); @@ -49,9 +51,13 @@ private: void drawParty(bool updateFlag); - void setupFaces(int firstDisplayChar, Common::Array<int> xeenSideChars, bool updateFlag); + void setupFaces(int firstDisplayChar, bool updateFlag); - void startingCharChanged(Common::Array<int> &charList, int firstDisplayChar); + void startingCharChanged(int firstDisplayChar); + + void createChar(); + + int selectCharacter(bool isDelete, int firstDisplayChar); public: static void show(XeenEngine *vm); }; diff --git a/engines/xeen/dialogs_quick_ref.cpp b/engines/xeen/dialogs_quick_ref.cpp index 6c8da5ef86..f4066a0de5 100644 --- a/engines/xeen/dialogs_quick_ref.cpp +++ b/engines/xeen/dialogs_quick_ref.cpp @@ -42,7 +42,7 @@ void QuickReferenceDialog::execute() { events.setCursor(0); for (uint idx = 0; idx < (combat._globalCombat == 2 ? party._combatParty.size() : - party._partyCount); ++idx) { + party._activeParty.size()); ++idx) { Character &c = combat._globalCombat == 2 ? *party._combatParty[idx] : party._activeParty[idx]; Condition condition = c.worstCondition(); @@ -59,7 +59,7 @@ void QuickReferenceDialog::execute() { ); } - int food = (party._food / party._partyCount) / 3; + int food = (party._food / party._activeParty.size()) / 3; Common::String msg = Common::String::format(QUICK_REFERENCE, lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(), lines[4].c_str(), lines[5].c_str(), diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index dc05be611d..0ce0259b45 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -111,7 +111,7 @@ Character *SpellsScroll::execute(Character *c, int v2) { case Common::KEYCODE_F6: if (_vm->_mode != MODE_COMBAT) { _buttonValue -= Common::KEYCODE_F1; - if (_buttonValue < party._partyCount) { + if (_buttonValue < (int)party._activeParty.size()) { c = &party._activeParty[_buttonValue]; spells._lastCaster = _buttonValue; intf.highlightChar(_buttonValue); diff --git a/engines/xeen/dialogs_whowill.cpp b/engines/xeen/dialogs_whowill.cpp index fb845a6d9a..10bbae26ee 100644 --- a/engines/xeen/dialogs_whowill.cpp +++ b/engines/xeen/dialogs_whowill.cpp @@ -44,7 +44,7 @@ int WhoWill::execute(int message, int action, bool type) { Town &town = *_vm->_town; int numFrames; - if (party._partyCount <= 1) + if (party._activeParty.size() <= 1) // Unless there's at least two characters, just return the first one return 1; @@ -53,7 +53,7 @@ int WhoWill::execute(int message, int action, bool type) { Common::String actionStr = type ? map._events._text[action] : WHO_WILL_ACTIONS[action]; Common::String msg = Common::String::format(WHO_WILL, actionStr.c_str(), - WHO_ACTIONS[message], party._partyCount); + WHO_ACTIONS[message], party._activeParty.size()); screen._windows[36].open(); screen._windows[36].writeString(msg); @@ -86,7 +86,7 @@ int WhoWill::execute(int message, int action, bool type) { break; } else if (_buttonValue >= 201 && _buttonValue <= 206) { _buttonValue -= 201; - if (_buttonValue > party._partyCount) + if (_buttonValue > (int)party._activeParty.size()) continue; if (party._activeParty[_buttonValue - 1].noActions()) diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 7c9e8a323a..b88b64af5f 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -433,7 +433,7 @@ void Interface::perform() { case Common::KEYCODE_F5: case Common::KEYCODE_F6: _buttonValue -= Common::KEYCODE_F1; - if (_buttonValue < party._partyCount) { + if (_buttonValue < (int)party._activeParty.size()) { CharacterInfo::show(_vm, _buttonValue); if (party._stepped) moveMonsters(); diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index beaf241f40..ad53b7c069 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -4397,8 +4397,8 @@ void InterfaceMap::drawIndoors() { // Check for any character shooting _isShooting = false; - for (int i = 0; i < _vm->_party->_partyCount; ++i) { - if (_vm->_combat->_shooting[i]) + for (uint idx = 0; idx < _vm->_party->_activeParty.size(); ++idx) { + if (_vm->_combat->_shooting[idx]) _isShooting = true; } @@ -4475,8 +4475,8 @@ void InterfaceMap::drawOutdoors() { // Check for any character shooting _isShooting = false; - for (int i = 0; i < _vm->_party->_partyCount; ++i) { - if (_vm->_combat->_shooting[i]) + for (uint idx = 0; idx < _vm->_party->_activeParty.size(); ++idx) { + if (_vm->_combat->_shooting[idx]) _isShooting = true; } diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index f14a0bfb1a..cd1dc21264 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -36,6 +36,9 @@ Roster::Roster() { resize(TOTAL_CHARACTERS); for (int idx = 0; idx < TOTAL_CHARACTERS; ++idx) { + // Set the index of the character in the roster list + operator[](idx)._rosterId = idx; + if (idx < XEEN_TOTAL_CHARACTERS) { // Load new character resource Common::String name = Common::String::format("char%02d.fac", idx + 1); @@ -48,7 +51,7 @@ Roster::Roster() { } void Roster::synchronize(Common::Serializer &s) { - for (uint i = 0; i < 30; ++i) + for (uint i = 0; i < TOTAL_CHARACTERS; ++i) (*this)[i].synchronize(s); } @@ -58,9 +61,6 @@ XeenEngine *Party::_vm; Party::Party(XeenEngine *vm) { _vm = vm; - _partyCount = 0; - _realPartyCount = 0; - Common::fill(&_partyMembers[0], &_partyMembers[8], 0); _mazeDirection = DIR_NORTH; _mazeId = _priorMazeId = 0; _levitateActive = false; @@ -120,11 +120,25 @@ Party::Party(XeenEngine *vm) { void Party::synchronize(Common::Serializer &s) { byte dummy[30]; Common::fill(&dummy[0], &dummy[30], 0); + int partyCount = _activeParty.size(); + + int8 partyMembers[MAX_PARTY_COUNT]; + if (s.isSaving()) { + Common::fill(&partyMembers[0], &partyMembers[8], -1); + for (uint idx = 0; idx < _activeParty.size(); ++idx) + partyMembers[idx] = _activeParty[idx]._rosterId; + } else { + _activeParty.clear(); + } + + s.syncAsByte(partyCount); // Party count + s.syncAsByte(partyCount); // Real party count + for (int idx = 0; idx < MAX_PARTY_COUNT; ++idx) { + s.syncAsByte(partyMembers[idx]); + if (s.isLoading() && idx < partyCount && partyMembers[idx] != -1) + _activeParty.push_back(_roster[partyMembers[idx]]); + } - s.syncAsByte(_partyCount); - s.syncAsByte(_realPartyCount); - for (int i = 0; i < 8; ++i) - s.syncAsByte(_partyMembers[i]); s.syncAsByte(_mazeDirection); s.syncAsByte(_mazePosition.x); s.syncAsByte(_mazePosition.y); @@ -199,10 +213,7 @@ void Party::synchronize(Common::Serializer &s) { } void Party::loadActiveParty() { - _activeParty.resize(_partyCount); - for (int i = 0; i < _partyCount; ++i) { - _activeParty[i] = _roster[_partyMembers[i]]; - } + // No implementation needed } bool Party::checkSkill(Skill skillId) { @@ -235,17 +246,20 @@ bool Party::checkSkill(Skill skillId) { } bool Party::isInParty(int charId) { - for (int i = 0; i < 8; ++i) { - if (_partyMembers[i] == charId) + for (uint i = 0; i < _activeParty.size(); ++i) { + if (_activeParty[i]._rosterId == charId) return true; } return false; } +/** + * Copy the currently active party characters' data back to the roster + */ void Party::copyPartyToRoster() { - for (int i = 0; i < _partyCount; ++i) { - _roster[_partyMembers[i]] = _activeParty[i]; + for (uint i = 0; i < _activeParty.size(); ++i) { + _roster[_activeParty[i]._rosterId] = _activeParty[i]; } } @@ -257,7 +271,7 @@ void Party::changeTime(int numMinutes) { bool killed = false; if (((_minutes + numMinutes) / 480) != (_minutes / 480)) { - for (int idx = 0; idx < _partyCount; ++idx) { + for (int idx = 0; idx < (int)_activeParty.size(); ++idx) { Character &player = _activeParty[idx]; if (!player._conditions[DEAD] && !player._conditions[STONED] && @@ -333,7 +347,7 @@ void Party::changeTime(int numMinutes) { // Increment the time addTime(numMinutes); - for (int idx = 0; idx < _partyCount; ++idx) { + for (int idx = 0; idx < (int)_activeParty.size(); ++idx) { Character &player = _activeParty[idx]; if (player._conditions[CONFUSED] && _vm->getRandomNumber(2) == 1) { @@ -383,7 +397,7 @@ void Party::addTime(int numMinutes) { if (_rested || _vm->_mode == MODE_SLEEPING) { _rested = false; } else { - for (int idx = 0; idx < _partyCount; ++idx) { + for (int idx = 0; idx < (int)_activeParty.size(); ++idx) { if (_activeParty[idx]._conditions[WEAK] >= 0) _activeParty[idx]._conditions[WEAK]++; } @@ -399,7 +413,7 @@ void Party::addTime(int numMinutes) { } void Party::resetTemps() { - for (int idx = 0; idx < _partyCount; ++idx) { + for (int idx = 0; idx < (int)_activeParty.size(); ++idx) { Character &player = _activeParty[idx]; player._magicResistence._temporary = 0; diff --git a/engines/xeen/party.h b/engines/xeen/party.h index a91b398931..58bfbd2c39 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -44,6 +44,7 @@ enum Difficulty { ADVENTURER = 0, WARRIOR = 1 }; #define TOTAL_CHARACTERS 30 #define XEEN_TOTAL_CHARACTERS 24 #define MAX_ACTIVE_PARTY 6 +#define MAX_PARTY_COUNT 8 #define TOTAL_STATS 7 #define TOTAL_QUEST_ITEMS 85 #define TOTAL_QUEST_FLAGS 56 @@ -64,9 +65,6 @@ private: static XeenEngine *_vm; public: // Dynamic data that's saved - int _partyCount; - int _realPartyCount; - int _partyMembers[8]; Direction _mazeDirection; Common::Point _mazePosition; int _mazeId; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index e9178505ad..d309fe9cd4 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1436,4 +1436,10 @@ const char *const SOME_CHARS_MAY_DIE = "Some Chars may die. Rest anyway?"; const char *const CANT_DISMISS_LAST_CHAR = "You cannot dismiss your last character!"; +const char *const REMOVE_DELETE[2] = { "Remove", "Delete" }; + +const char *const REMOVE_OR_DELETE_WHICH = "\x3l\t010\v005%s which character?"; + +const char *const YOUR_PARTY_IS_FULL = "\v007Your party is full!"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index d4e1c11694..a1734ce323 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -495,6 +495,11 @@ extern const char *const SOME_CHARS_MAY_DIE; extern const char *const CANT_DISMISS_LAST_CHAR; +extern const char *const REMOVE_DELETE[2]; +extern const char *const REMOVE_OR_DELETE_WHICH; + +extern const char *const YOUR_PARTY_IS_FULL; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 7ced6afa3f..6ab4c1fe13 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -426,7 +426,7 @@ void Scripts::cmdIf(Common::Array<byte> ¶ms) { result = ifProc(params[0], mask, _event->_opcode - 8, _charIndex - 1); } else { result = false; - for (int idx = 0; idx < party._partyCount && !result; ++idx) { + for (int idx = 0; idx < (int)party._activeParty.size() && !result; ++idx) { if (_charIndex == 0 || (_charIndex == 8 && idx != _v2)) { result = ifProc(params[0], mask, _event->_opcode - 8, idx); } @@ -488,7 +488,7 @@ void Scripts::cmdSetChar(Common::Array<byte> ¶ms) { return; } } else { - _charIndex = _vm->getRandomNumber(1, _vm->_party->_partyCount); + _charIndex = _vm->getRandomNumber(1, _vm->_party->_activeParty.size()); } _v2 = 1; @@ -576,7 +576,7 @@ void Scripts::cmdGiveExtended(Common::Array<byte> ¶ms) { result = ifProc(params[0], mask, _event->_opcode - OP_If1, _charIndex - 1); } else { result = false; - for (int idx = 0; idx < party._partyCount && !result; ++idx) { + for (int idx = 0; idx < (int)party._activeParty.size() && !result; ++idx) { if (_charIndex == 0 || (_charIndex == 8 && _v2 != idx)) { result = ifProc(params[0], mask, _event->_opcode - OP_If1, idx); } @@ -726,7 +726,7 @@ void Scripts::cmdSetVar(Common::Array<byte> ¶ms) { party._activeParty[_charIndex - 1].setValue(params[0], val); } else { // Set value for entire party - for (int idx = 0; idx < party._partyCount; ++idx) { + for (int idx = 0; idx < (int)party._activeParty.size(); ++idx) { if (_charIndex == 0 || (_charIndex == 8 && _v2 != idx)) { party._activeParty[idx].setValue(params[0], val); } @@ -870,7 +870,7 @@ void Scripts::doEndGame2() { Party &party = *_vm->_party; int v2 = 0; - for (int idx = 0; idx < party._partyCount; ++idx) { + for (uint idx = 0; idx < party._activeParty.size(); ++idx) { Character &player = party._activeParty[idx]; if (player.hasAward(77)) { v2 = 2; diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 25f332a010..f68a554b5f 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -532,7 +532,7 @@ Character *Town::doBlacksmithOptions(Character *c) { if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) { // Switch character _buttonValue -= Common::KEYCODE_F1; - if (_buttonValue < party._partyCount) { + if (_buttonValue < (int)party._activeParty.size()) { c = &party._activeParty[_buttonValue]; intf.highlightChar(_buttonValue); } @@ -554,7 +554,7 @@ Character *Town::doGuildOptions(Character *c) { if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) { // Switch character _buttonValue -= Common::KEYCODE_F1; - if (_buttonValue < party._partyCount) { + if (_buttonValue < (int)party._activeParty.size()) { c = &party._activeParty[_buttonValue]; intf.highlightChar(_buttonValue); @@ -598,7 +598,7 @@ Character *Town::doTavernOptions(Character *c) { case Common::KEYCODE_F6: // Switch character _buttonValue -= Common::KEYCODE_F1; - if (_buttonValue < party._partyCount) { + if (_buttonValue < (int)party._activeParty.size()) { c = &party._activeParty[_buttonValue]; intf.highlightChar(_buttonValue); _v21 = 0; @@ -632,27 +632,27 @@ Character *Town::doTavernOptions(Character *c) { case Common::KEYCODE_f: { // Food if (party._mazeId == (isDarkCc ? 29 : 28)) { - _v22 = party._partyCount * 15; + _v22 = party._activeParty.size() * 15; _v23 = 10; idx = 0; } else if (isDarkCc && party._mazeId == 31) { - _v22 = party._partyCount * 60; + _v22 = party._activeParty.size() * 60; _v23 = 100; idx = 1; } else if (!isDarkCc && party._mazeId == 30) { - _v22 = party._partyCount * 50; + _v22 = party._activeParty.size() * 50; _v23 = 50; idx = 1; } else if (isDarkCc) { - _v22 = party._partyCount * 120; + _v22 = party._activeParty.size() * 120; _v23 = 250; idx = 2; } else if (party._mazeId == 49) { - _v22 = party._partyCount * 120; + _v22 = party._activeParty.size() * 120; _v23 = 100; idx = 2; } else { - _v22 = party._partyCount * 15; + _v22 = party._activeParty.size() * 15; _v23 = 10; idx = 0; } @@ -717,7 +717,7 @@ Character *Town::doTavernOptions(Character *c) { party._mazeDirection = DIR_SOUTH; party._priorMazeId = party._mazeId; - for (int idx = 0; idx < party._partyCount; ++idx) { + for (uint idx = 0; idx < party._activeParty.size(); ++idx) { party._activeParty[idx]._savedMazeId = party._mazeId; party._activeParty[idx]._xeenSide = map._loadDarkSide; } @@ -799,7 +799,7 @@ Character *Town::doTempleOptions(Character *c) { case Common::KEYCODE_F6: // Switch character _buttonValue -= Common::KEYCODE_F1; - if (_buttonValue < party._partyCount) { + if (_buttonValue < (int)party._activeParty.size()) { c = &party._activeParty[_buttonValue]; intf.highlightChar(_buttonValue); _dayOfWeek = 0; @@ -900,7 +900,7 @@ Character *Town::doTrainingOptions(Character *c) { case Common::KEYCODE_F6: // Switch character _buttonValue -= Common::KEYCODE_F1; - if (_buttonValue < party._partyCount) { + if (_buttonValue < (int)party._activeParty.size()) { _v2 = _buttonValue; c = &party._activeParty[_buttonValue]; intf.highlightChar(_buttonValue); -- cgit v1.2.3 From 2f39bd5cd259cd5af16543338f4bb6a930191786 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 11 Feb 2015 20:04:38 -0500 Subject: XEEN: Fixes for display of party dialog --- engines/xeen/dialogs_party.cpp | 20 ++++++++++++-------- engines/xeen/dialogs_party.h | 4 +--- engines/xeen/interface.cpp | 5 +++++ engines/xeen/resources.cpp | 3 +++ engines/xeen/resources.h | 1 + 5 files changed, 22 insertions(+), 11 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index 618d29781d..9de0346cc6 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -32,6 +32,7 @@ namespace Xeen { PartyDialog::PartyDialog(XeenEngine *vm) : ButtonContainer(), PartyDrawer(vm), _vm(vm) { + initDrawStructs(); } void PartyDialog::show(XeenEngine *vm) { @@ -68,7 +69,7 @@ void PartyDialog::execute() { Window &w = screen._windows[11]; w.open(); setupFaces(startingChar, false); - w.writeString(_displayText); + w.writeString(Common::String::format(PARTY_DIALOG_TEXT, _partyDetails.c_str())); w.drawList(&_faceDrawStructs[0], 4); _uiSprites.draw(w, 0, Common::Point(16, 100)); @@ -99,8 +100,10 @@ void PartyDialog::execute() { bool breakFlag = false; while (!_vm->shouldQuit() && !breakFlag) { - events.pollEventsAndWait(); - checkEvents(_vm); + do { + events.pollEventsAndWait(); + checkEvents(_vm); + } while (!_vm->shouldQuit() && !_buttonValue); switch (_buttonValue) { case Common::KEYCODE_ESCAPE: @@ -226,7 +229,7 @@ void PartyDialog::loadButtons() { addButton(Common::Rect(87, 100, 111, 120), Common::KEYCODE_d, &_uiSprites); addButton(Common::Rect(122, 100, 146, 120), Common::KEYCODE_r, &_uiSprites); addButton(Common::Rect(157, 100, 181, 120), Common::KEYCODE_c, &_uiSprites); - addButton(Common::Rect(192, 100, 116, 120), Common::KEYCODE_x, &_uiSprites); + addButton(Common::Rect(192, 100, 216, 120), Common::KEYCODE_x, &_uiSprites); addButton(Common::Rect(0, 0, 0, 0), Common::KEYCODE_ESCAPE, &_uiSprites, false); addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_uiSprites, false); addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_uiSprites, false); @@ -247,7 +250,7 @@ void PartyDialog::setupBackground() { } /** - * Sets up the faces for display in the party dialog + * Sets up the faces from the avaialble roster for display in the party dialog */ void PartyDialog::setupFaces(int firstDisplayChar, bool updateFlag) { Party &party = *_vm->_party; @@ -285,10 +288,11 @@ void PartyDialog::setupFaces(int firstDisplayChar, bool updateFlag) { if ((firstDisplayChar + posIndex) >= (int)_charList.size()) _faceDrawStructs[posIndex]._sprites = nullptr; else - _faceDrawStructs[posIndex]._sprites = party._roster[posIndex]._faceSprites; + _faceDrawStructs[posIndex]._sprites = party._roster[ + _charList[firstDisplayChar + posIndex]]._faceSprites; } - _displayText = Common::String::format(PARTY_DETAILS, + _partyDetails = Common::String::format(PARTY_DETAILS, charNames[0].c_str(), charRaces[0].c_str(), charSex[0].c_str(), charClasses[0].c_str(), charNames[1].c_str(), charRaces[1].c_str(), charSex[1].c_str(), charClasses[1].c_str(), charNames[2].c_str(), charRaces[2].c_str(), charSex[2].c_str(), charClasses[2].c_str(), @@ -300,7 +304,7 @@ void PartyDialog::startingCharChanged(int firstDisplayChar) { Window &w = _vm->_screen->_windows[11]; setupFaces(firstDisplayChar, true); - w.writeString(_displayText); + w.writeString(_partyDetails); w.drawList(_faceDrawStructs, 4); _uiSprites.draw(w, 0, Common::Point(16, 100)); diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h index 082c43bb22..1510b76093 100644 --- a/engines/xeen/dialogs_party.h +++ b/engines/xeen/dialogs_party.h @@ -36,7 +36,7 @@ private: XeenEngine *_vm; SpriteResource _uiSprites; DrawStruct _faceDrawStructs[4]; - Common::String _displayText; + Common::String _partyDetails; Common::Array<int> _charList; PartyDialog(XeenEngine *vm); @@ -49,8 +49,6 @@ private: void setupBackground(); - void drawParty(bool updateFlag); - void setupFaces(int firstDisplayChar, bool updateFlag); void startingCharChanged(int firstDisplayChar); diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index b88b64af5f..b8e6437f2a 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -31,6 +31,8 @@ #include "xeen/resources.h" #include "xeen/xeen.h" +#include "xeen/dialogs_party.h" + namespace Xeen { PartyDrawer::PartyDrawer(XeenEngine *vm): _vm(vm) { @@ -501,6 +503,9 @@ void Interface::perform() { Quests::show(_vm); break; + case Common::KEYCODE_x: + // ****DEBUG*** + PartyDialog::show(_vm); //***DEBUG**** default: break; } diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index d309fe9cd4..d79ef8061d 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -354,6 +354,9 @@ const char *const PARTY_DETAILS = "\015\003l\002\014""00" "\013""052""\011""136%s" "\013""060""\011""136%s" "\013""068""\011""136%s"; +const char *const PARTY_DIALOG_TEXT = + "%s\x2\x3""c\v106\t013Up\t048Down\t083\f37D\fdel\t118\f37R\fdem" + "\t153\f37C\fdreate\t188E\f37x\fdit\x1"; const int FACE_CONDITION_FRAMES[17] = { 2, 2, 2, 1, 1, 4, 4, 4, 3, 2, 4, 3, 3, 5, 6, 7, 0 diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index a1734ce323..0e90a29a68 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -105,6 +105,7 @@ extern const char *const HEROISM; extern const char *const IN_PARTY; extern const char *const PARTY_DETAILS; +extern const char *const PARTY_DIALOG_TEXT; extern const int FACE_CONDITION_FRAMES[17]; -- cgit v1.2.3 From 6548dd05e316588bde3eae5db10793f8c6effd7b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 11 Feb 2015 21:04:05 -0500 Subject: XEEN: Fix removing and adding chars to party in Party dialog --- engines/xeen/dialogs.cpp | 9 +++++++ engines/xeen/dialogs.h | 2 ++ engines/xeen/dialogs_error.cpp | 4 ++- engines/xeen/dialogs_party.cpp | 61 ++++++++++++++++++++++++++++-------------- 4 files changed, 55 insertions(+), 21 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index ff4eaf622a..33eda14414 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -51,6 +51,15 @@ void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResou _buttons.push_back(UIButton(bounds, val, sprites, draw)); } +void ButtonContainer::addPartyButtons(XeenEngine *vm) { + Party &party = *vm->_party; + + for (uint idx = 0; idx < party._activeParty.size(); ++idx) { + addButton(Common::Rect(CHAR_FACES_X[idx], 150, CHAR_FACES_X[idx] + 32, 182), + Common::KEYCODE_F1 + idx, nullptr, false); + } +} + bool ButtonContainer::checkEvents(XeenEngine *vm) { EventsManager &events = *vm->_events; _buttonValue = 0; diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h index d8a9123c10..ba27fe97ec 100644 --- a/engines/xeen/dialogs.h +++ b/engines/xeen/dialogs.h @@ -67,6 +67,8 @@ public: void restoreButtons(); void addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw = true); + + void addPartyButtons(XeenEngine *vm); }; class SettingsBaseDialog : public ButtonContainer { diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp index 4fe39db3b3..db2603ab87 100644 --- a/engines/xeen/dialogs_error.cpp +++ b/engines/xeen/dialogs_error.cpp @@ -44,7 +44,7 @@ void ErrorDialog::execute(const Common::String &msg, ErrorWaitType waitType) { switch (waitType) { case WT_FREEZE_WAIT: - while (!_vm->shouldQuit() && !events.isKeyPending()) + while (!_vm->shouldQuit() && !events.isKeyMousePressed()) events.pollEventsAndWait(); events.clearEvents(); @@ -71,6 +71,8 @@ void ErrorDialog::execute(const Common::String &msg, ErrorWaitType waitType) { default: break; } + + w.close(); } /*------------------------------------------------------------------------*/ diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index 9de0346cc6..e1a6dbc92a 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -56,7 +56,8 @@ void PartyDialog::execute() { while (!_vm->shouldQuit()) { _vm->_mode = MODE_1; - // Build up a list of characters on the same Xeen side being loaded + // Build up a list of available characters in the Roster that are on the + // same side of Xeen as the player is currently on _charList.clear(); for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) { Character &player = party._roster[i]; @@ -159,28 +160,37 @@ void PartyDialog::execute() { break; } + // Only add the character if they're not already in the party if (idx == party._activeParty.size()) { - sound.playFX(21); - ErrorScroll::show(_vm, YOUR_PARTY_IS_FULL); - } else { - party._activeParty.push_back(party._roster[ - _charList[_buttonValue - 7 + startingChar]]); - error("TODO"); + if (party._activeParty.size() == MAX_ACTIVE_PARTY) { + sound.playFX(21); + ErrorScroll::show(_vm, YOUR_PARTY_IS_FULL); + } else { + // Add the character to the active party + party._activeParty.push_back(party._roster[ + _charList[_buttonValue - 7 + startingChar]]); + startingCharChanged(startingChar); + } } } - // TODO break; case Common::KEYCODE_UP: case Common::KEYCODE_KP8: + // Up arrow if (startingChar > 0) { startingChar -= 4; startingCharChanged(startingChar); } break; + case Common::KEYCODE_DOWN: case Common::KEYCODE_KP2: - // TODO + // Down arrow + if (startingChar < (_charList.size() - 4)) { + startingChar += 4; + startingCharChanged(startingChar); + } break; case Common::KEYCODE_c: @@ -231,10 +241,6 @@ void PartyDialog::loadButtons() { addButton(Common::Rect(157, 100, 181, 120), Common::KEYCODE_c, &_uiSprites); addButton(Common::Rect(192, 100, 216, 120), Common::KEYCODE_x, &_uiSprites); addButton(Common::Rect(0, 0, 0, 0), Common::KEYCODE_ESCAPE, &_uiSprites, false); - addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_uiSprites, false); - addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_uiSprites, false); - addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3, &_uiSprites, false); - addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4, &_uiSprites, false); } void PartyDialog::initDrawStructs() { @@ -261,6 +267,15 @@ void PartyDialog::setupFaces(int firstDisplayChar, bool updateFlag) { int posIndex; int charId; + // Reset the button areas for the display character images + while (_buttons.size() > 7) + _buttons.remove_at(7); + addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_uiSprites, false); + addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_uiSprites, false); + addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3, &_uiSprites, false); + addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4, &_uiSprites, false); + + for (posIndex = 0; posIndex < 4; ++posIndex) { charId = (firstDisplayChar + posIndex) >= (int)_charList.size() ? -1 : _charList[firstDisplayChar + posIndex]; @@ -304,7 +319,7 @@ void PartyDialog::startingCharChanged(int firstDisplayChar) { Window &w = _vm->_screen->_windows[11]; setupFaces(firstDisplayChar, true); - w.writeString(_partyDetails); + w.writeString(Common::String::format(PARTY_DIALOG_TEXT, _partyDetails.c_str())); w.drawList(_faceDrawStructs, 4); _uiSprites.draw(w, 0, Common::Point(16, 100)); @@ -344,6 +359,7 @@ int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) { addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &iconSprites, false); addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3, &iconSprites, false); addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4, &iconSprites, false); + addPartyButtons(_vm); int result = -1, v; while (!_vm->shouldQuit() && result == -1) { @@ -364,18 +380,23 @@ int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) { case Common::KEYCODE_F4: case Common::KEYCODE_F5: case Common::KEYCODE_F6: - v = _buttonValue - Common::KEYCODE_F1; - if (v < (int)party._activeParty.size()) - result = _buttonValue; + if (!isDelete) { + v = _buttonValue - Common::KEYCODE_F1; + if (v < (int)party._activeParty.size()) + result = _buttonValue; + } break; case Common::KEYCODE_1: case Common::KEYCODE_2: case Common::KEYCODE_3: case Common::KEYCODE_4: - v = _buttonValue - Common::KEYCODE_1; - if ((firstDisplayChar + v) < (int)_charList.size()) - result = _buttonValue; + if (isDelete) { + v = _buttonValue - Common::KEYCODE_1; + if ((firstDisplayChar + v) < (int)_charList.size()) + result = _buttonValue; + } + break; default: break; -- cgit v1.2.3 From a39b0b24a1dccec3e91f45deb047fa027372d84f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 11 Feb 2015 21:09:07 -0500 Subject: XEEN: Fix changing selected character with mouse in various dialogs --- engines/xeen/dialogs.cpp | 2 +- engines/xeen/dialogs_char_info.cpp | 1 + engines/xeen/dialogs_items.cpp | 1 + engines/xeen/interface.cpp | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index 33eda14414..a2535fdf02 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -54,7 +54,7 @@ void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResou void ButtonContainer::addPartyButtons(XeenEngine *vm) { Party &party = *vm->_party; - for (uint idx = 0; idx < party._activeParty.size(); ++idx) { + for (uint idx = 0; idx < MAX_ACTIVE_PARTY; ++idx) { addButton(Common::Rect(CHAR_FACES_X[idx], 150, CHAR_FACES_X[idx] + 32, 182), Common::KEYCODE_F1 + idx, nullptr, false); } diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp index de16e9559e..df4b699a72 100644 --- a/engines/xeen/dialogs_char_info.cpp +++ b/engines/xeen/dialogs_char_info.cpp @@ -274,6 +274,7 @@ void CharacterInfo::addButtons() { addButton(Common::Rect(285, 43, 309, 63), Common::KEYCODE_q, &_iconSprites); addButton(Common::Rect(285, 75, 309, 95), Common::KEYCODE_e, &_iconSprites); addButton(Common::Rect(285, 107, 309, 127), Common::KEYCODE_ESCAPE, &_iconSprites); + addPartyButtons(_vm); } /** diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index 7b4e23eb01..d37d124a7c 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -557,6 +557,7 @@ void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) { addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, &_iconSprites, false); addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, &_iconSprites, false); addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, &_iconSprites, false); + addPartyButtons(_vm); } if (mode == ITEMMODE_BLACKSMITH) { diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index b8e6437f2a..0916abe26c 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -219,6 +219,7 @@ void Interface::setMainButtons() { addButton(Common::Rect(239, 27, 312, 37), Common::KEYCODE_1, &_iconSprites, false); addButton(Common::Rect(239, 37, 312, 47), Common::KEYCODE_2, &_iconSprites, false); addButton(Common::Rect(239, 47, 312, 57), Common::KEYCODE_3, &_iconSprites, false); + addPartyButtons(_vm); } /** -- cgit v1.2.3 From 2772cd33c1f62d0e0ea41507f6b809704d569254 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 11 Feb 2015 23:37:03 -0500 Subject: XEEN: Implemented code for deleting characters in Party dialog --- engines/xeen/character.cpp | 9 +++++++++ engines/xeen/character.h | 2 ++ engines/xeen/dialogs_party.cpp | 41 ++++++++++++++++++++++++++++++++++++++++- engines/xeen/resources.cpp | 5 +++++ engines/xeen/resources.h | 3 +++ 5 files changed, 59 insertions(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index e7b5d23ecc..ac25b32c55 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -1787,5 +1787,14 @@ void Character::subtractHitPoints(int amount) { } } +bool Character::hasSpecialItem() const { + for (uint idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + if (_weapons[idx]._id == 34) + // Character has Xeen Slayer sword + return true; + } + + return false; +} } // End of namespace Xeen diff --git a/engines/xeen/character.h b/engines/xeen/character.h index 59f4ba65b6..492e5e298f 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -315,6 +315,8 @@ public: int makeItem(int p1, int itemIndex, int p3); void subtractHitPoints(int amount); + + bool hasSpecialItem() const; }; } // End of namespace Xeen diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index e1a6dbc92a..eece1e36fe 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -23,6 +23,7 @@ #include "common/scummsys.h" #include "xeen/dialogs_char_info.h" #include "xeen/dialogs_party.h" +#include "xeen/dialogs_query.h" #include "xeen/character.h" #include "xeen/events.h" #include "xeen/party.h" @@ -187,7 +188,7 @@ void PartyDialog::execute() { case Common::KEYCODE_DOWN: case Common::KEYCODE_KP2: // Down arrow - if (startingChar < (_charList.size() - 4)) { + if (startingChar < ((int)_charList.size() - 4)) { startingChar += 4; startingCharChanged(startingChar); } @@ -210,9 +211,47 @@ void PartyDialog::execute() { breakFlag = true; } break; + case Common::KEYCODE_d: // Delete character + if (_charList.size() > 0) { + int charButtonValue = selectCharacter(true, startingChar); + if (charButtonValue != 0) { + int charIndex = charButtonValue - Common::KEYCODE_1 + startingChar; + Character &c = party._roster[_charList[charIndex]]; + if (c.hasSpecialItem()) { + ErrorScroll::show(_vm, HAS_SLAYER_SWORD); + } else { + Common::String msg = Common::String::format(SURE_TO_DELETE_CHAR, + c._name.c_str(), CLASS_NAMES[c._class]); + if (Confirm::show(_vm, msg)) { + // If the character is in the party, remove it + for (uint idx = 0; idx < party._activeParty.size(); ++idx) { + if (party._activeParty[idx]._rosterId == c._rosterId) { + party._activeParty.remove_at(idx); + break; + } + } + + // Empty the character in the roster + c.clear(); + + // Rebuild the character list + _charList.clear(); + for (int idx = 0; idx < XEEN_TOTAL_CHARACTERS; ++idx) { + Character &c = party._roster[idx]; + if (!c._name.empty() && c._savedMazeId == party._priorMazeId) { + _charList.push_back(idx); + } + } + + startingCharChanged(startingChar); + } + } + } + } break; + case Common::KEYCODE_r: // Remove character if (party._activeParty.size() > 0) { diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index d79ef8061d..8f1475308d 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1445,4 +1445,9 @@ const char *const REMOVE_OR_DELETE_WHICH = "\x3l\t010\v005%s which character?"; const char *const YOUR_PARTY_IS_FULL = "\v007Your party is full!"; +const char *const HAS_SLAYER_SWORD = + "\v000\t000This character has the Xeen Slayer Sword and cannot be deleted!"; +const char *const SURE_TO_DELETE_CHAR = + "Are you sure you want to delete %s the %s?"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 0e90a29a68..2ca9dbbfda 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -501,6 +501,9 @@ extern const char *const REMOVE_OR_DELETE_WHICH; extern const char *const YOUR_PARTY_IS_FULL; +extern const char *const HAS_SLAYER_SWORD; +extern const char *const SURE_TO_DELETE_CHAR; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From e16ecd110b2f607621773e13df8f972c9c7e979a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 12 Feb 2015 23:16:20 -0500 Subject: XEEN: Implementing create chracter dialog --- engines/xeen/character.h | 4 +- engines/xeen/dialogs_party.cpp | 246 ++++++++++++++++++++++++++++++++++++++++- engines/xeen/dialogs_party.h | 12 ++ engines/xeen/resources.cpp | 21 ++++ engines/xeen/resources.h | 7 ++ 5 files changed, 287 insertions(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.h b/engines/xeen/character.h index 492e5e298f..9e8687dbd7 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -49,13 +49,13 @@ enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 }; enum CharacterClass { CLASS_KNIGHT = 0, CLASS_PALADIN = 1, CLASS_ARCHER = 2, CLASS_CLERIC = 3, CLASS_SORCERER = 4, CLASS_ROBBER = 5, CLASS_NINJA = 6, CLASS_BARBARIAN = 7, - CLASS_DRUID = 8, CLASS_RANGER = 9, + CLASS_DRUID = 8, CLASS_RANGER = 9, TOTAL_CLASSES = 10, CLASS_12 = 12, CLASS_15 = 15, CLASS_16 = 16 }; enum Attribute { MIGHT = 0, INTELLECT = 1, PERSONALITY = 2, ENDURANCE = 3, SPEED = 4, - ACCURACY = 5, LUCK = 6 + ACCURACY = 5, LUCK = 6, TOTAL_ATTRIBUTES = 7 }; enum Skill { diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index eece1e36fe..ff59363ead 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -372,7 +372,136 @@ void PartyDialog::startingCharChanged(int firstDisplayChar) { } void PartyDialog::createChar() { - error("TODO: createChar"); + EventsManager &events = *_vm->_events; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + SpriteResource dice, icons; + Mode oldMode = _vm->_mode; + Common::Array<int> freeCharList; + int selectedClass = 0; + bool hasFadedIn = false; + + dice.load("dice.vga"); + icons.load("create.raw"); + + // Add buttons + saveButtons(); + addButton(Common::Rect(132, 98, 156, 118), Common::KEYCODE_r, &icons); + addButton(Common::Rect(132, 128, 156, 148), Common::KEYCODE_c, &icons); + addButton(Common::Rect(132, 158, 156, 178), Common::KEYCODE_ESCAPE, &icons); + addButton(Common::Rect(86, 98, 110, 118), Common::KEYCODE_UP, &icons); + addButton(Common::Rect(86, 120, 110, 140), Common::KEYCODE_DOWN, &icons); + addButton(Common::Rect(168, 19, 192, 39), Common::KEYCODE_n, nullptr); + addButton(Common::Rect(168, 43, 192, 63), Common::KEYCODE_i, nullptr); + addButton(Common::Rect(168, 67, 192, 87), Common::KEYCODE_p, nullptr); + addButton(Common::Rect(168, 91, 192, 111), Common::KEYCODE_e, nullptr); + addButton(Common::Rect(168, 115, 192, 135), Common::KEYCODE_s, nullptr); + addButton(Common::Rect(168, 139, 192, 159), Common::KEYCODE_a, nullptr); + addButton(Common::Rect(168, 163, 192, 183), Common::KEYCODE_l, nullptr); + addButton(Common::Rect(227, 19, 139, 29), 1000, nullptr); + addButton(Common::Rect(227, 30, 139, 40), 1001, nullptr); + addButton(Common::Rect(227, 41, 139, 51), 1002, nullptr); + addButton(Common::Rect(227, 52, 139, 62), 1003, nullptr); + addButton(Common::Rect(227, 63, 139, 73), 1004, nullptr); + addButton(Common::Rect(227, 74, 139, 84), 1005, nullptr); + addButton(Common::Rect(227, 85, 139, 95), 1006, nullptr); + addButton(Common::Rect(227, 96, 139, 106), 1007, nullptr); + addButton(Common::Rect(227, 107, 139, 117), 1008, nullptr); + addButton(Common::Rect(227, 118, 139, 128), 1009, nullptr); + + // Load the background + screen.loadBackground("create.raw"); + events.setCursor(0); + + while (!_vm->shouldQuit()) { + int classId = -1; + + // Build up list of roster slot indexes that are free + freeCharList.clear(); + for (uint idx = 0; idx < XEEN_TOTAL_CHARACTERS; ++idx) { + if (party._roster[idx]._name.empty()) + freeCharList.push_back(idx); + } + int charIndex = 0; + //bool flag9 = true; + + if (freeCharList.size() == XEEN_TOTAL_CHARACTERS) + break; + + // Get and race and sex for the given character + Race race = (Race)((freeCharList[charIndex] / 4) % 5); + Sex sex = (Sex)(freeCharList[charIndex] & 1); + + // Randomly determine attributes, and which classes they allow + uint attribs[TOTAL_ATTRIBUTES]; + bool allowedClasses[TOTAL_CLASSES]; + throwDice(attribs, allowedClasses); + + // Set up display of the rolled character details + Common::String msg; + selectedClass = newCharDetails(attribs, allowedClasses, + race, sex, classId, selectedClass, msg); + + // Draw the screen + Window &w = screen._windows[0]; + icons.draw(w, 10, Common::Point(168, 19)); + icons.draw(w, 12, Common::Point(168, 43)); + icons.draw(w, 14, Common::Point(168, 67)); + icons.draw(w, 16, Common::Point(168, 91)); + icons.draw(w, 18, Common::Point(168, 115)); + icons.draw(w, 20, Common::Point(168, 139)); + icons.draw(w, 22, Common::Point(168, 163)); + for (int idx = 0; idx < 9; ++idx) + icons.draw(w, 24 + idx * 2, Common::Point(227, 19 + 11 * idx)); + + for (int idx = 0; idx < 7; ++idx) + icons.draw(w, 50 + idx, Common::Point(195, 31 + 24 * idx)); + + icons.draw(w, 57, Common::Point(62, 148)); + icons.draw(w, 58, Common::Point(62, 158)); + icons.draw(w, 59, Common::Point(62, 168)); + icons.draw(w, 61, Common::Point(220, 19)); + icons.draw(w, 64, Common::Point(220, 155)); + icons.draw(w, 65, Common::Point(220, 170)); + + party._roster[freeCharList[charIndex]]._faceSprites->draw( + w, 0, Common::Point(27, 102)); + + icons.draw(w, 0, Common::Point(132, 98)); + icons.draw(w, 2, Common::Point(132, 128)); + icons.draw(w, 4, Common::Point(132, 158)); + icons.draw(w, 6, Common::Point(86, 98)); + icons.draw(w, 8, Common::Point(86, 120)); + + w.writeString(msg); + w.update(); + + // Draw the arrow for the selected class, if applicable + if (selectedClass != -1) + printSelectionArrow(icons, selectedClass); + + // Draw the dice + drawDice(dice); + if (!hasFadedIn) { + screen.fadeIn(4); + hasFadedIn = true; + } + + // Key handling loop + while (!_vm->shouldQuit()) { + // Animate the dice until a user action occurs + _buttonValue = 0; + while (!_vm->shouldQuit() && !_buttonValue) + drawDice(dice); + + // TODO + } + + // TODO: More + error("TODO: createChar"); + } + + _vm->_mode = oldMode; } int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) { @@ -447,4 +576,119 @@ int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) { return result == -1 ? 0 : result; } +/** + * Roll up some random values for the attributes, and return both them as + * well as a list of classes that the attributes meet the requirements for + */ +void PartyDialog::throwDice(uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]) { + bool repeat = true; + do { + // Default all the attributes to zero + Common::fill(&attribs[0], &attribs[TOTAL_ATTRIBUTES], 0); + + // Assign random amounts to each attribute + for (int idx1 = 0; idx1 < 3; ++idx1) { + for (int idx2 = 0; idx2 < TOTAL_ATTRIBUTES; ++idx2) { + attribs[idx1] += _vm->getRandomNumber(10, 79) / 10; + } + } + + // Check which classes are allowed based on the rolled attributes + checkClass(attribs, allowedClasses); + + // Only exit if the attributes allow for at least one class + for (int idx = 0; idx < TOTAL_CLASSES; ++idx) { + if (allowedClasses[idx]) + repeat = false; + } + } while (repeat); +} + +/** + * Set a list of flags for which classes the passed attribute set meet the + * minimum requirements of + */ +void PartyDialog::checkClass(const uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]) { + allowedClasses[CLASS_KNIGHT] = attribs[MIGHT] >= 15; + allowedClasses[CLASS_PALADIN] = attribs[MIGHT] >= 13 + && attribs[PERSONALITY] >= 13 && attribs[ENDURANCE] >= 13; + allowedClasses[CLASS_ARCHER] = attribs[INTELLECT] >= 13 && attribs[ACCURACY] >= 13; + allowedClasses[CLASS_CLERIC] = attribs[PERSONALITY] >= 13; + allowedClasses[CLASS_SORCERER] = attribs[INTELLECT] >= 13; + allowedClasses[CLASS_ROBBER] = attribs[LUCK] >= 13; + allowedClasses[CLASS_NINJA] = attribs[SPEED] >= 13 && attribs[ACCURACY] >= 13; + allowedClasses[CLASS_BARBARIAN] = attribs[ENDURANCE] >= 15; + allowedClasses[CLASS_DRUID] = attribs[INTELLECT] >= 15 && attribs[PERSONALITY] >= 15; + allowedClasses[CLASS_RANGER] = attribs[INTELLECT] >= 12 && attribs[PERSONALITY] >= 12 + && attribs[ENDURANCE] >= 12 && attribs[SPEED] >= 12; +} + +/** + * Return details of the generated character + */ +int PartyDialog::newCharDetails(const uint attribs[TOTAL_ATTRIBUTES], + bool allowedClasses[TOTAL_CLASSES], Race race, Sex sex, int classId, + int selectedClass, Common::String &msg) { + int foundClass = -1; + Common::String skillStr, classStr, raceSkillStr; + + // If a selected class is provided, set the default skill for that class + if (classId != -1 && NEW_CHAR_SKILLS[classId] != -1) { + const char *skillP = SKILL_NAMES[NEW_CHAR_SKILLS[classId]]; + skillStr = Common::String(skillP, skillP + NEW_CHAR_SKILLS_LEN[classId]); + } + + // If a class is provided, set the class name + if (classId != -1) { + classStr = Common::String::format("\t062\v168%s", CLASS_NAMES[classId]); + } + + // Set up default skill for the race, if any + if (NEW_CHAR_RACE_SKILLS[race] != -1) { + raceSkillStr = SKILL_NAMES[NEW_CHAR_RACE_SKILLS[race]]; + } + + // Set up color to use for each skill string to be displayed, based + // on whether each class is allowed or not for the given attributes + int classColors[TOTAL_CLASSES]; + Common::fill(&classColors[0], &classColors[TOTAL_CLASSES], 0); + for (int classNum = CLASS_KNIGHT; classNum <= CLASS_RANGER; ++classNum) { + if (allowedClasses[classNum]) { + if (classId == -1 && (foundClass == -1 || foundClass < classNum)) + foundClass = classNum; + classColors[classNum] = 4; + } + } + + // Return stats details and character class + msg = Common::String::format(NEW_CHAR_STATS, RACE_NAMES[race], SEX_NAMES[sex], + attribs[MIGHT], attribs[INTELLECT], attribs[PERSONALITY], + attribs[ENDURANCE], attribs[SPEED], attribs[ACCURACY], attribs[LUCK], + classColors[CLASS_KNIGHT], classColors[CLASS_PALADIN], + classColors[CLASS_ARCHER], classColors[CLASS_CLERIC], + classColors[CLASS_SORCERER], classColors[CLASS_ROBBER], + classColors[CLASS_NINJA], classColors[CLASS_BARBARIAN], + classColors[CLASS_DRUID], classColors[CLASS_RANGER], + skillStr.c_str(), raceSkillStr.c_str(), classStr.c_str() + ); + return classId == -1 ? foundClass : selectedClass; +} + +/** + * Print the selection arrow to indicate the selected class + */ +void PartyDialog::printSelectionArrow(SpriteResource &icons, int selectedClass) { + Window &w = _vm->_screen->_windows[0]; + icons.draw(w, 61, Common::Point(220, 19)); + icons.draw(w, 63, Common::Point(220, selectedClass * 11 + 21)); + w.update(); +} + +/** + * Print the dice animation + */ +void PartyDialog::drawDice(SpriteResource &dice) { + error("TODO: drawDice"); +} + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h index 1510b76093..e9b06ae732 100644 --- a/engines/xeen/dialogs_party.h +++ b/engines/xeen/dialogs_party.h @@ -56,6 +56,18 @@ private: void createChar(); int selectCharacter(bool isDelete, int firstDisplayChar); + + void throwDice(uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]); + + void checkClass(const uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]); + + int newCharDetails(const uint attribs[TOTAL_ATTRIBUTES], + bool allowedClasses[TOTAL_CLASSES], Race race, Sex sex, int classId, + int selectedClass, Common::String &msg); + + void printSelectionArrow(SpriteResource &icons, int selectedClass); + + void drawDice(SpriteResource &dice); public: static void show(XeenEngine *vm); }; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 8f1475308d..b11db9ff82 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1450,4 +1450,25 @@ const char *const HAS_SLAYER_SWORD = const char *const SURE_TO_DELETE_CHAR = "Are you sure you want to delete %s the %s?"; +const char *const CREATE_CHAR_DETAILS = + "\f04\x3""c\x2\t144\v119\f37R\f04oll\t144\v149\f37C\f04reate" + "\t144\v179\f37ESC\f04\x3l\x1\t195\v021\f37M\f04gt" + "\t195\v045\f37I\f04nt\t195\v069\f37P\f04er\t195\v093\f37E\f04nd" + "\t195\v116\f37S\f04pd\t195\v140\f37A\f04cy\t195\v164\f37L\f04ck%s"; + +const char *const NEW_CHAR_STATS = + "\f04\x3l\t022\v148Race\t055: %s\n" + "\t022Sex\t055: %s\n" + "\t022Class\t055:\n" + "\x3r\t215\v031%d\t215\v055%d\t215\v079%d\t215\v103%d\t215\v127%d" + "\t215\v151%d\t215\v175%d\x3l\t242\v020\f%2dKnight\t242\v031\f%2d" + "Paladin\t242\v042\f%2dArcher\t242\v053\f%2dCleric\t242\v064\f%2d" + "Sorcerer\t242\v075\f%2dRobber\t242\v086\f%2dNinja\t242\v097\f%2d" + "Barbarian\t242\v108\f%2dDruid\t242\v119\f%2dRanger\f04\x3""c" + "\t265\v142Skills\x3l\t223\v155%s\t223\v170%s%s"; + +const int NEW_CHAR_SKILLS[10] = { 1, 5, -1, -1, 4, 0, 0, -1, 6, 11 }; +const int NEW_CHAR_SKILLS_LEN[10] = { 11, 8, 0, 0, 12, 8, 8, 0, 9, 11 }; +const int NEW_CHAR_RACE_SKILLS[10] = { 14, -1, 17, 16, -1, 0, 0, 0, 0, 0 }; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 2ca9dbbfda..3c1ae9dbd0 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -504,6 +504,13 @@ extern const char *const YOUR_PARTY_IS_FULL; extern const char *const HAS_SLAYER_SWORD; extern const char *const SURE_TO_DELETE_CHAR; +extern const char *const CREATE_CHAR_DETAILS; + +extern const char *const NEW_CHAR_STATS; +extern const int NEW_CHAR_SKILLS[10]; +extern const int NEW_CHAR_SKILLS_LEN[10]; +extern const int NEW_CHAR_RACE_SKILLS[10]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From d225bc4cb3364b2cc8fc0fcab96347cc91e93866 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 13 Feb 2015 23:20:23 -0500 Subject: XEEN: Implemented saveCharacter --- engines/xeen/dialogs.cpp | 12 +- engines/xeen/dialogs_input.cpp | 9 + engines/xeen/dialogs_input.h | 3 + engines/xeen/dialogs_party.cpp | 417 +++++++++++++++++++++++++++++++++-------- engines/xeen/dialogs_party.h | 5 + engines/xeen/resources.cpp | 23 +++ engines/xeen/resources.h | 10 + engines/xeen/xeen.h | 3 +- 8 files changed, 401 insertions(+), 81 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index a2535fdf02..8bb0af0833 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -52,8 +52,6 @@ void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResou } void ButtonContainer::addPartyButtons(XeenEngine *vm) { - Party &party = *vm->_party; - for (uint idx = 0; idx < MAX_ACTIVE_PARTY; ++idx) { addButton(Common::Rect(CHAR_FACES_X[idx], 150, CHAR_FACES_X[idx] + 32, 182), Common::KEYCODE_F1 + idx, nullptr, false); @@ -80,7 +78,15 @@ bool ButtonContainer::checkEvents(XeenEngine *vm) { Common::KeyState keyState; events.getKey(keyState); - _buttonValue = keyState.keycode | (keyState.flags << 8); + _buttonValue = keyState.keycode; + if (_buttonValue == Common::KEYCODE_KP8) + _buttonValue = Common::KEYCODE_UP; + else if (_buttonValue == Common::KEYCODE_KP2) + _buttonValue = Common::KEYCODE_DOWN; + else if (_buttonValue == Common::KEYCODE_KP_ENTER) + _buttonValue = Common::KEYCODE_RETURN; + + _buttonValue |= (keyState.flags << 8); if (_buttonValue) return true; } diff --git a/engines/xeen/dialogs_input.cpp b/engines/xeen/dialogs_input.cpp index 1394379910..042fabf102 100644 --- a/engines/xeen/dialogs_input.cpp +++ b/engines/xeen/dialogs_input.cpp @@ -26,6 +26,15 @@ namespace Xeen { +int Input::show(XeenEngine *vm, Window *window, Common::String &line, + uint maxLen, int maxWidth, bool isNumeric) { + Input *dlg = new Input(vm, window); + int result = dlg->getString(line, maxLen, maxWidth, isNumeric); + delete dlg; + + return result; +} + /** * Allows the user to enter a string */ diff --git a/engines/xeen/dialogs_input.h b/engines/xeen/dialogs_input.h index c6d832ce6b..30e4cb2854 100644 --- a/engines/xeen/dialogs_input.h +++ b/engines/xeen/dialogs_input.h @@ -39,6 +39,9 @@ protected: int getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric); Input(XeenEngine *vm, Window *window) : _vm(vm), _window(window) {} +public: + static int show(XeenEngine *vm, Window *window, Common::String &line, + uint maxLen, int maxWidth, bool isNumeric = false); }; class StringInput : public Input { diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index ff59363ead..058ead4edc 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -23,6 +23,7 @@ #include "common/scummsys.h" #include "xeen/dialogs_char_info.h" #include "xeen/dialogs_party.h" +#include "xeen/dialogs_input.h" #include "xeen/dialogs_query.h" #include "xeen/character.h" #include "xeen/events.h" @@ -375,12 +376,22 @@ void PartyDialog::createChar() { EventsManager &events = *_vm->_events; Party &party = *_vm->_party; Screen &screen = *_vm->_screen; + Window &w = screen._windows[0]; SpriteResource dice, icons; - Mode oldMode = _vm->_mode; Common::Array<int> freeCharList; + int classId; int selectedClass = 0; bool hasFadedIn = false; + bool restartFlag = true; + uint attribs[TOTAL_ATTRIBUTES]; + bool allowedClasses[TOTAL_CLASSES]; + Race race; + Sex sex; + Common::String msg; + int charIndex; + Mode oldMode = _vm->_mode; + _vm->_mode = MODE_4; dice.load("dice.vga"); icons.load("create.raw"); @@ -414,93 +425,261 @@ void PartyDialog::createChar() { events.setCursor(0); while (!_vm->shouldQuit()) { - int classId = -1; - - // Build up list of roster slot indexes that are free - freeCharList.clear(); - for (uint idx = 0; idx < XEEN_TOTAL_CHARACTERS; ++idx) { - if (party._roster[idx]._name.empty()) - freeCharList.push_back(idx); - } - int charIndex = 0; - //bool flag9 = true; - - if (freeCharList.size() == XEEN_TOTAL_CHARACTERS) - break; + classId = -1; + + if (restartFlag) { + // Build up list of roster slot indexes that are free + freeCharList.clear(); + for (uint idx = 0; idx < XEEN_TOTAL_CHARACTERS; ++idx) { + if (party._roster[idx]._name.empty()) + freeCharList.push_back(idx); + } + charIndex = 0; + //bool flag9 = true; - // Get and race and sex for the given character - Race race = (Race)((freeCharList[charIndex] / 4) % 5); - Sex sex = (Sex)(freeCharList[charIndex] & 1); - - // Randomly determine attributes, and which classes they allow - uint attribs[TOTAL_ATTRIBUTES]; - bool allowedClasses[TOTAL_CLASSES]; - throwDice(attribs, allowedClasses); - - // Set up display of the rolled character details - Common::String msg; - selectedClass = newCharDetails(attribs, allowedClasses, - race, sex, classId, selectedClass, msg); - - // Draw the screen - Window &w = screen._windows[0]; - icons.draw(w, 10, Common::Point(168, 19)); - icons.draw(w, 12, Common::Point(168, 43)); - icons.draw(w, 14, Common::Point(168, 67)); - icons.draw(w, 16, Common::Point(168, 91)); - icons.draw(w, 18, Common::Point(168, 115)); - icons.draw(w, 20, Common::Point(168, 139)); - icons.draw(w, 22, Common::Point(168, 163)); - for (int idx = 0; idx < 9; ++idx) - icons.draw(w, 24 + idx * 2, Common::Point(227, 19 + 11 * idx)); - - for (int idx = 0; idx < 7; ++idx) - icons.draw(w, 50 + idx, Common::Point(195, 31 + 24 * idx)); - - icons.draw(w, 57, Common::Point(62, 148)); - icons.draw(w, 58, Common::Point(62, 158)); - icons.draw(w, 59, Common::Point(62, 168)); - icons.draw(w, 61, Common::Point(220, 19)); - icons.draw(w, 64, Common::Point(220, 155)); - icons.draw(w, 65, Common::Point(220, 170)); - - party._roster[freeCharList[charIndex]]._faceSprites->draw( - w, 0, Common::Point(27, 102)); + if (freeCharList.size() == XEEN_TOTAL_CHARACTERS) + break; + + // Get and race and sex for the given character + race = (Race)((freeCharList[charIndex] / 4) % 5); + sex = (Sex)(freeCharList[charIndex] & 1); + + // Randomly determine attributes, and which classes they allow + throwDice(attribs, allowedClasses); + + // Set up display of the rolled character details + selectedClass = newCharDetails(attribs, allowedClasses, + race, sex, classId, selectedClass, msg); + + // Draw the screen + icons.draw(w, 10, Common::Point(168, 19)); + icons.draw(w, 12, Common::Point(168, 43)); + icons.draw(w, 14, Common::Point(168, 67)); + icons.draw(w, 16, Common::Point(168, 91)); + icons.draw(w, 18, Common::Point(168, 115)); + icons.draw(w, 20, Common::Point(168, 139)); + icons.draw(w, 22, Common::Point(168, 163)); + for (int idx = 0; idx < 9; ++idx) + icons.draw(w, 24 + idx * 2, Common::Point(227, 19 + 11 * idx)); + + for (int idx = 0; idx < 7; ++idx) + icons.draw(w, 50 + idx, Common::Point(195, 31 + 24 * idx)); + + icons.draw(w, 57, Common::Point(62, 148)); + icons.draw(w, 58, Common::Point(62, 158)); + icons.draw(w, 59, Common::Point(62, 168)); + icons.draw(w, 61, Common::Point(220, 19)); + icons.draw(w, 64, Common::Point(220, 155)); + icons.draw(w, 65, Common::Point(220, 170)); + + party._roster[freeCharList[charIndex]]._faceSprites->draw( + w, 0, Common::Point(27, 102)); + + icons.draw(w, 0, Common::Point(132, 98)); + icons.draw(w, 2, Common::Point(132, 128)); + icons.draw(w, 4, Common::Point(132, 158)); + icons.draw(w, 6, Common::Point(86, 98)); + icons.draw(w, 8, Common::Point(86, 120)); + + w.writeString(msg); + w.update(); + + // Draw the arrow for the selected class, if applicable + if (selectedClass != -1) + printSelectionArrow(icons, selectedClass); + + // Draw the dice + drawDice(dice); + if (!hasFadedIn) { + screen.fadeIn(4); + hasFadedIn = true; + } + + restartFlag = false; + } + + // Animate the dice until a user action occurs + _buttonValue = 0; + while (!_vm->shouldQuit() && !_buttonValue) + drawDice(dice); + + // Handling for different actions + switch (_buttonValue) { + case Common::KEYCODE_UP: + if (charIndex == 0) + continue; + + race = (Race)((freeCharList[charIndex] / 4) % 5); + sex = (Sex)(freeCharList[charIndex] & 1); + break; - icons.draw(w, 0, Common::Point(132, 98)); - icons.draw(w, 2, Common::Point(132, 128)); - icons.draw(w, 4, Common::Point(132, 158)); - icons.draw(w, 6, Common::Point(86, 98)); - icons.draw(w, 8, Common::Point(86, 120)); + case Common::KEYCODE_DOWN: + if (++charIndex == (int)freeCharList.size()) { + --charIndex; + continue; + } else { + race = (Race)((freeCharList[charIndex] / 4) % 5); + sex = (Sex)(freeCharList[charIndex] & 1); + } + break; - w.writeString(msg); - w.update(); + case Common::KEYCODE_PAGEUP: + for (int tempClass = selectedClass - 1; tempClass >= 0; --tempClass) { + if (allowedClasses[tempClass]) { + selectedClass = tempClass; + break; + } + } - // Draw the arrow for the selected class, if applicable - if (selectedClass != -1) printSelectionArrow(icons, selectedClass); + continue; - // Draw the dice - drawDice(dice); - if (!hasFadedIn) { - screen.fadeIn(4); - hasFadedIn = true; + case Common::KEYCODE_PAGEDOWN: + break; + + case Common::KEYCODE_m: + case Common::KEYCODE_i: + case Common::KEYCODE_p: + case Common::KEYCODE_e: + case Common::KEYCODE_s: + case Common::KEYCODE_a: + case Common::KEYCODE_l: { + Attribute srcAttrib, destAttrib; + if (_buttonValue == Common::KEYCODE_m) + srcAttrib = MIGHT; + else if (_buttonValue == Common::KEYCODE_i) + srcAttrib = INTELLECT; + else if (_buttonValue == Common::KEYCODE_p) + srcAttrib = PERSONALITY; + else if (_buttonValue == Common::KEYCODE_e) + srcAttrib = ENDURANCE; + else if (_buttonValue == Common::KEYCODE_s) + srcAttrib = SPEED; + else if (_buttonValue == Common::KEYCODE_a) + srcAttrib = ACCURACY; + else + srcAttrib = LUCK; + + _vm->_mode = MODE_86; + icons.draw(w, srcAttrib * 2 + 11, Common::Point( + _buttons[srcAttrib + 5]._bounds.left, _buttons[srcAttrib + 5]._bounds.top)); + w.update(); + + int destAttribVal = exchangeAttribute(srcAttrib + 1); + if (destAttribVal) { + destAttrib = (Attribute)(destAttribVal - 1); + icons.draw(w, destAttrib * 2 + 11, Common::Point( + _buttons[destAttrib + 10]._bounds.left, + _buttons[destAttrib + 10]._bounds.top)); + w.update(); + + SWAP(attribs[srcAttrib], attribs[destAttrib]); + checkClass(attribs, allowedClasses); + classId = -1; + selectedClass = newCharDetails(attribs, allowedClasses, + race, sex, classId, selectedClass, msg); + } else { + icons.draw(w, srcAttrib * 2 + 10, Common::Point( + _buttons[srcAttrib + 5]._bounds.left, + _buttons[srcAttrib + 5]._bounds.top)); + w.update(); + _vm->_mode = MODE_SLEEPING; + continue; + } + break; } - // Key handling loop - while (!_vm->shouldQuit()) { - // Animate the dice until a user action occurs - _buttonValue = 0; - while (!_vm->shouldQuit() && !_buttonValue) - drawDice(dice); + case 1000: + case 1001: + case 1002: + case 1003: + case 1004: + case 1005: + case 1006: + case 1007: + case 1008: + case 1009: + if (allowedClasses[_buttonValue - 1000]) { + selectedClass = classId = _buttonValue - 1000; + } + break; + + case Common::KEYCODE_c: { + _vm->_mode = MODE_FF; + bool result = saveCharacter(party._roster[freeCharList[charIndex]], + (CharacterClass)classId, race, sex, attribs); + _vm->_mode = MODE_4; - // TODO + if (result) + restartFlag = true; + continue; } - - // TODO: More - error("TODO: createChar"); - } + case Common::KEYCODE_RETURN: + classId = selectedClass; + break; + + case Common::KEYCODE_SPACE: + case Common::KEYCODE_r: + // Re-roll the attributes + throwDice(attribs, allowedClasses); + classId = -1; + break; + + default: + // For all other keypresses, skip the code below the switch + // statement, and go to wait for the next key + continue; + } + + if (_buttonValue != Common::KEYCODE_PAGEDOWN) { + selectedClass = newCharDetails(attribs, allowedClasses, + race, sex, classId, selectedClass, msg); + + for (int idx = 0; idx < 7; ++idx) + icons.draw(w, 10 + idx * 2, Common::Point(168, 19 + idx * 24)); + for (int idx = 0; idx < 10; ++idx) + icons.draw(w, 24 + idx * 2, Common::Point(227, 19 + idx * 11)); + for (int idx = 0; idx < 8; ++idx) + icons.draw(w, 50 + idx, Common::Point(195, 31 + idx * 24)); + + icons.draw(w, 57, Common::Point(62, 148)); + icons.draw(w, 58, Common::Point(62, 158)); + icons.draw(w, 59, Common::Point(62, 168)); + icons.draw(w, 61, Common::Point(220, 19)); + icons.draw(w, 64, Common::Point(220, 155)); + icons.draw(w, 65, Common::Point(220, 170)); + + party._roster[freeCharList[charIndex]]._faceSprites->draw(w, 0, + Common::Point(27, 102)); + + icons.draw(w, 0, Common::Point(132, 98)); + icons.draw(w, 2, Common::Point(132, 128)); + icons.draw(w, 4, Common::Point(132, 158)); + icons.draw(w, 6, Common::Point(86, 98)); + icons.draw(w, 8, Common::Point(86, 120)); + + w.writeString(msg); + w.update(); + + if (selectedClass != -1) { + printSelectionArrow(icons, selectedClass); + continue; + } + } + + // Move to next available class, or if the code block above resulted in + // selectedClass being -1, move to select the first available class + for (int tempClass = selectedClass + 1; tempClass <= CLASS_RANGER; ++tempClass) { + if (allowedClasses[tempClass]) { + selectedClass = tempClass; + break; + } + } + + printSelectionArrow(icons, selectedClass); + } while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE); + _vm->_mode = oldMode; } @@ -691,4 +870,88 @@ void PartyDialog::drawDice(SpriteResource &dice) { error("TODO: drawDice"); } +/** + * Exchanging two attributes for the character being rolled + */ +int PartyDialog::exchangeAttribute(int srcAttr) { + error("TODO: exchangeAttribute"); +} + +bool PartyDialog::saveCharacter(Character &c, CharacterClass classId, + Race race, Sex sex, uint attribs[TOTAL_ATTRIBUTES]) { + if (classId == -1) { + ErrorScroll::show(_vm, SELECT_CLASS_BEFORE_SAVING); + return false; + } + + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + Window &w = screen._windows[6]; + Common::String name; + int result; + bool isDarkCc = _vm->_files->_isDarkCc; + + saveButtons(); + w.writeString(NAME_FOR_NEW_CHARACTER); + + result = Input::show(_vm, &w, name, 10, 200); + w.close(); + restoreButtons(); + if (!result) + return false; + + // Save new character details + c.clear(); + c._name = name; + c._savedMazeId = party._priorMazeId; + c._xeenSide = map._loadDarkSide; + c._sex = sex; + c._race = race; + c._class = classId; + c._level._permanent = isDarkCc ? 5 : 1; + + c._might._permanent = attribs[MIGHT]; + c._intellect._permanent = attribs[INTELLECT]; + c._personality._permanent = attribs[PERSONALITY]; + c._endurance._permanent = attribs[ENDURANCE]; + c._speed._permanent = attribs[SPEED]; + c._accuracy._permanent = attribs[ACCURACY]; + c._luck._permanent = attribs[LUCK]; + + c._magicResistence._permanent = RACE_MAGIC_RESISTENCES[race]; + c._fireResistence._permanent = RACE_FIRE_RESISTENCES[race]; + c._electricityResistence._permanent = RACE_ELECTRIC_RESISTENCES[race]; + c._coldResistence._permanent = RACE_COLD_RESISTENCES[race]; + c._energyResistence._permanent = RACE_ENERGY_RESISTENCES[race]; + c._poisonResistence._permanent = RACE_POISON_RESISTENCES[race]; + + c._birthYear = party._year - 18; + c._birthDay = party._day; + c._hasSpells = false; + c._currentSpell = -1; + + // Set up any default spells for the character's class + for (int idx = 0; idx < 4; ++idx) { + if (NEW_CHARACTER_SPELLS[c._class][idx] != -1) { + c._hasSpells = true; + c._currentSpell = NEW_CHARACTER_SPELLS[c._class][idx]; + c._spells[c._currentSpell] = 1; + } + } + + int classSkill = NEW_CHAR_SKILLS[c._class]; + if (classSkill != -1) + c._skills[classSkill] = 1; + + int raceSkill = NEW_CHAR_RACE_SKILLS[c._race]; + if (raceSkill != -1) + c._skills[raceSkill] = 1; + + c._currentHp = c.getMaxHP(); + c._currentSp = c.getMaxSP(); + return true; +} + + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h index e9b06ae732..178a5c4991 100644 --- a/engines/xeen/dialogs_party.h +++ b/engines/xeen/dialogs_party.h @@ -68,6 +68,11 @@ private: void printSelectionArrow(SpriteResource &icons, int selectedClass); void drawDice(SpriteResource &dice); + + int exchangeAttribute(int srcAttr); + + bool saveCharacter(Character &c, CharacterClass classId, Race race, + Sex sex, uint attribs[TOTAL_ATTRIBUTES]); public: static void show(XeenEngine *vm); }; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index b11db9ff82..c9c377d3a6 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1467,8 +1467,31 @@ const char *const NEW_CHAR_STATS = "Barbarian\t242\v108\f%2dDruid\t242\v119\f%2dRanger\f04\x3""c" "\t265\v142Skills\x3l\t223\v155%s\t223\v170%s%s"; +const char *const NAME_FOR_NEW_CHARACTER = + "\x3""cEnter a Name for this Character"; +const char *const SELECT_CLASS_BEFORE_SAVING = + "\v006\x3""cSelect a Class before saving.\x3l"; const int NEW_CHAR_SKILLS[10] = { 1, 5, -1, -1, 4, 0, 0, -1, 6, 11 }; const int NEW_CHAR_SKILLS_LEN[10] = { 11, 8, 0, 0, 12, 8, 8, 0, 9, 11 }; const int NEW_CHAR_RACE_SKILLS[10] = { 14, -1, 17, 16, -1, 0, 0, 0, 0, 0 }; +const int RACE_MAGIC_RESISTENCES[5] = { 7, 5, 20, 0, 0 }; +const int RACE_FIRE_RESISTENCES[5] = { 7, 0, 2, 5, 10 }; +const int RACE_ELECTRIC_RESISTENCES[5] = { 7, 0, 2, 5, 10 }; +const int RACE_COLD_RESISTENCES[5] = { 7, 0, 2, 5, 10 }; +const int RACE_ENERGY_RESISTENCES[5] = { 7, 5, 2, 5, 0 }; +const int RACE_POISON_RESISTENCES[5] = { 7, 0, 2, 20, 0 }; +const int NEW_CHARACTER_SPELLS[10][4] = { + { -1, -1, -1, -1 }, + { 21, -1, -1, -1 }, + { 22, -1, -1, -1 }, + { 21, 1, 14, -1 }, + { 22, 0, 25, -1 }, + { -1, -1, -1, -1 }, + { -1, -1, -1, -1 }, + { -1, -1, -1, -1 }, + { 20, 1, 11, 23 }, + { 20, 1, -1, -1 } +}; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 3c1ae9dbd0..3c6df78a8f 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -507,10 +507,20 @@ extern const char *const SURE_TO_DELETE_CHAR; extern const char *const CREATE_CHAR_DETAILS; extern const char *const NEW_CHAR_STATS; +extern const char *const NAME_FOR_NEW_CHARACTER; +extern const char *const SELECT_CLASS_BEFORE_SAVING; extern const int NEW_CHAR_SKILLS[10]; extern const int NEW_CHAR_SKILLS_LEN[10]; extern const int NEW_CHAR_RACE_SKILLS[10]; +extern const int RACE_MAGIC_RESISTENCES[5]; +extern const int RACE_FIRE_RESISTENCES[5]; +extern const int RACE_ELECTRIC_RESISTENCES[5]; +extern const int RACE_COLD_RESISTENCES[5]; +extern const int RACE_ENERGY_RESISTENCES[5]; +extern const int RACE_POISON_RESISTENCES[5]; +extern const int NEW_CHARACTER_SPELLS[10][4]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index c4f826d508..2d85335ced 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -88,7 +88,8 @@ enum Mode { MODE_9 = 9, MODE_CHARACTER_INFO = 10, MODE_12 = 12, - MODE_17 = 17 + MODE_17 = 17, + MODE_86 = 86 }; struct XeenGameDescription; -- cgit v1.2.3 From 9b0b0cd9e747780ec32a3589343f0172c0237aa0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 13 Feb 2015 23:48:02 -0500 Subject: XEEN: Implemented exchangeAttribute --- engines/xeen/dialogs.h | 3 +- engines/xeen/dialogs_party.cpp | 77 ++++++++++++++++++++++++++++++++++++++++-- engines/xeen/resources.cpp | 2 ++ engines/xeen/resources.h | 1 + 4 files changed, 80 insertions(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h index ba27fe97ec..02e945b665 100644 --- a/engines/xeen/dialogs.h +++ b/engines/xeen/dialogs.h @@ -66,7 +66,8 @@ public: void restoreButtons(); - void addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw = true); + void addButton(const Common::Rect &bounds, int val, + SpriteResource *sprites = nullptr, bool draw = true); void addPartyButtons(XeenEngine *vm); }; diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index 058ead4edc..b570612ff4 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -874,9 +874,83 @@ void PartyDialog::drawDice(SpriteResource &dice) { * Exchanging two attributes for the character being rolled */ int PartyDialog::exchangeAttribute(int srcAttr) { - error("TODO: exchangeAttribute"); + EventsManager &events = *_vm->_events; + Screen &screen = *_vm->_screen; + SpriteResource icons; + icons.load("create2.icn"); + + saveButtons(); + addButton(Common::Rect(118, 58, 142, 78), Common::KEYCODE_ESCAPE, &icons); + addButton(Common::Rect(168, 19, 192, 39), Common::KEYCODE_m); + addButton(Common::Rect(168, 43, 192, 63), Common::KEYCODE_i); + addButton(Common::Rect(168, 67, 192, 87), Common::KEYCODE_p); + addButton(Common::Rect(168, 91, 192, 111), Common::KEYCODE_e); + addButton(Common::Rect(168, 115, 192, 135), Common::KEYCODE_s); + addButton(Common::Rect(168, 139, 192, 159), Common::KEYCODE_a); + addButton(Common::Rect(168, 163, 192, 183), Common::KEYCODE_l); + + Window &w = screen._windows[26]; + w.open(); + w.writeString(Common::String::format(EXCHANGE_ATTR_WITH, STAT_NAMES[srcAttr - 1])); + icons.draw(w, 0, Common::Point(118, 58)); + w.update(); + + int result = 0; + bool breakFlag = false; + while (!_vm->shouldQuit() && !breakFlag) { + // Wait for an action + do { + events.pollEventsAndWait(); + checkEvents(_vm); + } while (!_vm->shouldQuit() && !_buttonValue); + + Attribute destAttr; + switch (_buttonValue) { + case Common::KEYCODE_m: + destAttr = MIGHT; + break; + case Common::KEYCODE_i: + destAttr = INTELLECT; + break; + case Common::KEYCODE_p: + destAttr = PERSONALITY; + break; + case Common::KEYCODE_e: + destAttr = ENDURANCE; + break; + case Common::KEYCODE_s: + destAttr = SPEED; + break; + case Common::KEYCODE_a: + destAttr = ACCURACY; + break; + case Common::KEYCODE_l: + destAttr = LUCK; + break; + case Common::KEYCODE_ESCAPE: + result = 0; + breakFlag = true; + continue; + default: + continue; + } + + if ((srcAttr - 1) != destAttr) { + result = destAttr + 1; + break; + } + } + + w.close(); + _buttonValue = 0; + restoreButtons(); + + return result; } +/** + * Saves the rolled character into the roster + */ bool PartyDialog::saveCharacter(Character &c, CharacterClass classId, Race race, Sex sex, uint attribs[TOTAL_ATTRIBUTES]) { if (classId == -1) { @@ -953,5 +1027,4 @@ bool PartyDialog::saveCharacter(Character &c, CharacterClass classId, return true; } - } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index c9c377d3a6..7dca04fd03 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1471,6 +1471,8 @@ const char *const NAME_FOR_NEW_CHARACTER = "\x3""cEnter a Name for this Character"; const char *const SELECT_CLASS_BEFORE_SAVING = "\v006\x3""cSelect a Class before saving.\x3l"; +const char *const EXCHANGE_ATTR_WITH = "Exchange %s with..."; + const int NEW_CHAR_SKILLS[10] = { 1, 5, -1, -1, 4, 0, 0, -1, 6, 11 }; const int NEW_CHAR_SKILLS_LEN[10] = { 11, 8, 0, 0, 12, 8, 8, 0, 9, 11 }; const int NEW_CHAR_RACE_SKILLS[10] = { 14, -1, 17, 16, -1, 0, 0, 0, 0, 0 }; diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 3c6df78a8f..53c548fbf5 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -509,6 +509,7 @@ extern const char *const CREATE_CHAR_DETAILS; extern const char *const NEW_CHAR_STATS; extern const char *const NAME_FOR_NEW_CHARACTER; extern const char *const SELECT_CLASS_BEFORE_SAVING; +extern const char *const EXCHANGE_ATTR_WITH; extern const int NEW_CHAR_SKILLS[10]; extern const int NEW_CHAR_SKILLS_LEN[10]; extern const int NEW_CHAR_RACE_SKILLS[10]; -- cgit v1.2.3 From b79d552c060b869a2f22727b4b7238294bc05943 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Feb 2015 07:32:38 -0500 Subject: XEEN: Implemented drawDice --- engines/xeen/dialogs_party.cpp | 43 +++++++++++++++++++++++++++++++++++++++++- engines/xeen/dialogs_party.h | 3 +++ 2 files changed, 45 insertions(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index b570612ff4..7414ce3404 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -395,6 +395,16 @@ void PartyDialog::createChar() { dice.load("dice.vga"); icons.load("create.raw"); + _dicePos[0] = Common::Point(20, 17); + _dicePos[1] = Common::Point(112, 35); + _dicePos[2] = Common::Point(61, 50); + _diceFrame[0] = 0; + _diceFrame[1] = 2; + _diceFrame[2] = 4; + _diceInc[0] = Common::Point(10, -10); + _diceInc[1] = Common::Point(-10, -10); + _diceInc[2] = Common::Point(-10, 10); + // Add buttons saveButtons(); addButton(Common::Rect(132, 98, 156, 118), Common::KEYCODE_r, &icons); @@ -867,7 +877,38 @@ void PartyDialog::printSelectionArrow(SpriteResource &icons, int selectedClass) * Print the dice animation */ void PartyDialog::drawDice(SpriteResource &dice) { - error("TODO: drawDice"); + EventsManager &events = *_vm->_events; + Window &w = _vm->_screen->_windows[32]; + dice.draw(w, 7, Common::Point(12, 11)); + + for (int diceNum = 0; diceNum < 3; ++diceNum) { + _diceFrame[diceNum] = (_diceFrame[diceNum] + 1) % 7; + _dicePos[diceNum] += _diceInc[diceNum]; + + if (_dicePos[diceNum].x < 13) { + _dicePos[diceNum].x = 13; + _diceInc[diceNum].x *= -1; + } else if (_dicePos[diceNum].x >= 163) { + _dicePos[diceNum].x = 163; + _diceInc[diceNum].x *= -1; + } + + if (_dicePos[diceNum].y < 12) { + _dicePos[diceNum].y = 12; + _diceInc[diceNum].y *= -1; + } else if (_dicePos[diceNum].y >= 93) { + _dicePos[diceNum].y = 93; + _diceInc[diceNum].y *= -1; + } + + dice.draw(w, _diceFrame[diceNum], _dicePos[diceNum]); + } + + w.update(); + + // Wait for keypress + events.wait(1, true); + checkEvents(_vm); } /** diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h index 178a5c4991..db2a3dfb36 100644 --- a/engines/xeen/dialogs_party.h +++ b/engines/xeen/dialogs_party.h @@ -38,6 +38,9 @@ private: DrawStruct _faceDrawStructs[4]; Common::String _partyDetails; Common::Array<int> _charList; + int _diceFrame[3]; + Common::Point _dicePos[3]; + Common::Point _diceInc[3]; PartyDialog(XeenEngine *vm); -- cgit v1.2.3 From cad435d9a04ac16bc1203854e1616464a35f7f20 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Feb 2015 08:25:36 -0500 Subject: XEEN: Fix default display of doors --- engines/xeen/interface_map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index ad53b7c069..262c9455fd 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -4314,7 +4314,7 @@ void InterfaceMap::drawIndoors() { if (_wo[107]) { _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - if (_vm->_openDoor) + if (!_vm->_openDoor) _indoorList._fwl_1F1R._frame = 0; else _indoorList._fwl_1F1R._frame = map.mazeData()._wallKind ? 1 : 10; -- cgit v1.2.3 From dae789369ed3ec4568e8149d9e5a3eca1d6b5d7b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 14 Feb 2015 08:36:40 -0500 Subject: XEEN: Fix _buttonValue check for moving through doorways --- engines/xeen/interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 0916abe26c..dc35b216b1 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -698,7 +698,7 @@ bool Interface::checkMoveDirection(int key) { sound.playFX(46); return false; } else { - if (_buttonValue == 242 && _wo[107]) { + if (_buttonValue == Common::KEYCODE_UP && _wo[107]) { _vm->_openDoor = true; sound.playFX(47); draw3d(true); -- cgit v1.2.3 From cc9f62fcb936f86468566cd33602ff394040d33a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Feb 2015 12:01:04 -0500 Subject: XEEN: Split up draw3d between Interface and InterfaceMap, start of fall code --- engines/xeen/interface.cpp | 111 +++++++++++++++++++++++++++++++++++++++++ engines/xeen/interface.h | 10 ++++ engines/xeen/interface_map.cpp | 43 +--------------- engines/xeen/interface_map.h | 4 +- 4 files changed, 124 insertions(+), 44 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index dc35b216b1..51a59e1f6f 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -932,5 +932,116 @@ void Interface::bash(const Common::Point &pt, Direction direction) { drawParty(true); } +void Interface::draw3d(bool updateFlag) { + Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + + if (screen._windows[11]._enabled) + return; + + // Draw the map + drawMap(updateFlag); + + // Draw the minimap + drawMiniMap(); + + if (party._falling == 1) + handleFalling(); + + if (party._falling == 2) { + screen.saveBackground(1); + } + + assembleBorder(); + + // Draw any on-screen text if flagged to do so + if (_upDoorText && combat._attackMonsters[0] == -1) { + screen._windows[3].writeString(_screenText); + } + + if (updateFlag) { + screen._windows[1].update(); + screen._windows[3].update(); + } + + // TODO: more stuff + + _vm->_party->_stepped = false; + if (_vm->_mode == MODE_9) { + // TODO + } + + // TODO: Check use of updateFlag here. Original doesn't have it, but I + // wanted to ensure in places like the AutoMapDialog, that the draw3d + // doesn't result in the screen updating until the dialog has had + // a chance to full render itself + if (updateFlag) + events.wait(2); +} + +void Interface::handleFalling() { + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + Window &w = screen._windows[3]; + File voc1("scream.voc"); + File voc2("unnh.voc"); + saveFall(); + + for (uint idx = 0; idx < party._activeParty.size(); ++idx) { + party._activeParty[idx]._faceSprites->draw(screen._windows[0], 4, + Common::Point(CHAR_FACES_X[idx], 150)); + } + + screen._windows[33].update(); + sound.playFX(11); + sound.playSample(&voc1, 0); + + for (int idx = 0, incr = 2; idx < 133; ++incr, idx += incr) { + fall(idx); + assembleBorder(); + w.update(); + } + + fall(132); + assembleBorder(); + w.update(); + + sound.playSample(nullptr, 0); + sound.playSample(&voc2, 0); + sound.playFX(31); + + fall(127); + assembleBorder(); + w.update(); + + fall(132); + assembleBorder(); + w.update(); + + fall(129); + assembleBorder(); + w.update(); + + fall(132); + assembleBorder(); + w.update(); + + shake(); +} + +void Interface::saveFall() { + +} + +void Interface::fall(int v) { + +} + +void Interface::shake() { + +} } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 59801757be..57db3f2bcd 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -85,6 +85,14 @@ private: void doStepCode(); bool checkMoveDirection(int key); + + void handleFalling(); + + void saveFall(); + + void fall(int v); + + void shake(); public: int _intrIndex1; Common::String _interfaceText; @@ -108,6 +116,8 @@ public: void rest(); void bash(const Common::Point &pt, Direction direction); + + void draw3d(bool updateFlag); }; } // End of namespace Xeen diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 262c9455fd..6893c7114a 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -406,12 +406,9 @@ void InterfaceMap::setup() { _charPowSprites.load("charpow.icn"); } -void InterfaceMap::draw3d(bool updateFlag) { +void InterfaceMap::drawMap(bool updateFlag) { Combat &combat = *_vm->_combat; - EventsManager &events = *_vm->_events; Map &map = *_vm->_map; - Party &party = *_vm->_party; - Screen &screen = *_vm->_screen; Scripts &scripts = *_vm->_scripts; const int COMBAT_POS_X[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } }; @@ -419,9 +416,6 @@ void InterfaceMap::draw3d(bool updateFlag) { const int OUTDOOR_INDEXES[3] = { 119, 113, 116 }; const int COMBAT_OFFSET_X[4] = { 8, 6, 4, 2 }; - if (screen._windows[11]._enabled) - return; - _flipUIFrame = (_flipUIFrame + 1) % 4; if (_flipUIFrame == 0) _flipWater = !_flipWater; @@ -727,41 +721,6 @@ void InterfaceMap::draw3d(bool updateFlag) { } animate3d(); - drawMiniMap(); - - if (party._falling == 1) { - error("TODO: Indoor falling"); - } - - if (party._falling == 2) { - screen.saveBackground(1); - } - - assembleBorder(); - - // Draw any on-screen text if flagged to do so - if (_upDoorText && combat._attackMonsters[0] == -1) { - screen._windows[3].writeString(_screenText); - } - - if (updateFlag) { - screen._windows[1].update(); - screen._windows[3].update(); - } - - // TODO: more stuff - - _vm->_party->_stepped = false; - if (_vm->_mode == MODE_9) { - // TODO - } - - // TODO: Check use of updateFlag here. Original doesn't have it, but I - // wanted to ensure in places like the AutoMapDialog, that the draw3d - // doesn't result in the screen updating until the dialog has had - // a chance to full render itself - if (updateFlag) - events.wait(2); } /** diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 660213a98e..b65b7d6fb9 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -126,6 +126,8 @@ protected: void drawMiniMap(); virtual void setup(); + + void drawMap(bool updateFlag); public: OutdoorDrawList _outdoorList; IndoorDrawList _indoorList; @@ -146,8 +148,6 @@ public: virtual ~InterfaceMap() {} - void draw3d(bool updateFlag); - void setIndoorsMonsters(); void setIndoorsObjects(); -- cgit v1.2.3 From 6605a0c505b2e58bd458fab6865e4db1bf55972b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Feb 2015 12:20:44 -0500 Subject: XEEN: Implemented more code from end of draw3d --- engines/xeen/combat.cpp | 6 ++++++ engines/xeen/combat.h | 2 ++ engines/xeen/interface.cpp | 22 ++++++++++++++++------ engines/xeen/interface.h | 2 +- engines/xeen/interface_map.cpp | 2 +- engines/xeen/interface_map.h | 2 +- 6 files changed, 27 insertions(+), 9 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index fec244b63a..4d0add115a 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -22,6 +22,7 @@ #include "xeen/combat.h" #include "common/algorithm.h" +#include "common/textconsole.h" namespace Xeen { @@ -42,4 +43,9 @@ void Combat::clear() { Common::fill(&_attackMonsters[0], &_attackMonsters[26], -1); } +void Combat::doCombat() { + error("TODO: doCombat"); +} + + } // End of namespace Xeen diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index ef82de5af2..c5c7f0817b 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -65,6 +65,8 @@ public: Combat(XeenEngine *vm); void clear(); + + void doCombat(); }; } // End of namespace Xeen diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 51a59e1f6f..89747d1a81 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -937,12 +937,13 @@ void Interface::draw3d(bool updateFlag) { EventsManager &events = *_vm->_events; Party &party = *_vm->_party; Screen &screen = *_vm->_screen; + Scripts &scripts = *_vm->_scripts; if (screen._windows[11]._enabled) return; // Draw the map - drawMap(updateFlag); + drawMap(); // Draw the minimap drawMiniMap(); @@ -966,11 +967,20 @@ void Interface::draw3d(bool updateFlag) { screen._windows[3].update(); } - // TODO: more stuff + if (combat._attackMonsters[0] != -1 || combat._attackMonsters[1] != -1 + || combat._attackMonsters[2] != -1) { + if ((_vm->_mode == MODE_1 || _vm->_mode == MODE_SLEEPING) && !_flag1 + && !_charsShooting && _vm->_moveMonsters) { + combat.doCombat(); + if (scripts._eventSkipped) + scripts.checkEvents(); + } + } - _vm->_party->_stepped = false; + party._stepped = false; if (_vm->_mode == MODE_9) { - // TODO + // TODO: Save current scripts data? + error("TODO: save scripts?"); } // TODO: Check use of updateFlag here. Original doesn't have it, but I @@ -1029,7 +1039,7 @@ void Interface::handleFalling() { assembleBorder(); w.update(); - shake(); + shake(10); } void Interface::saveFall() { @@ -1040,7 +1050,7 @@ void Interface::fall(int v) { } -void Interface::shake() { +void Interface::shake(int time) { } diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 57db3f2bcd..660d1b1340 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -92,7 +92,7 @@ private: void fall(int v); - void shake(); + void shake(int time); public: int _intrIndex1; Common::String _interfaceText; diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 6893c7114a..a098800f28 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -406,7 +406,7 @@ void InterfaceMap::setup() { _charPowSprites.load("charpow.icn"); } -void InterfaceMap::drawMap(bool updateFlag) { +void InterfaceMap::drawMap() { Combat &combat = *_vm->_combat; Map &map = *_vm->_map; Scripts &scripts = *_vm->_scripts; diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index b65b7d6fb9..3fe851b2e8 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -127,7 +127,7 @@ protected: virtual void setup(); - void drawMap(bool updateFlag); + void drawMap(); public: OutdoorDrawList _outdoorList; IndoorDrawList _indoorList; -- cgit v1.2.3 From a90ad5b4c18ad067b0839f22a24a09db69570ac8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Feb 2015 12:26:23 -0500 Subject: XEEN: Move drawMiniMap to Interface class --- engines/xeen/interface.cpp | 377 +++++++++++++++++++++++++++++++++++++++++ engines/xeen/interface.h | 2 + engines/xeen/interface_map.cpp | 376 ---------------------------------------- engines/xeen/interface_map.h | 2 - 4 files changed, 379 insertions(+), 378 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 89747d1a81..f81e5186c7 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -1054,4 +1054,381 @@ void Interface::shake(int time) { } +void Interface::drawMiniMap() { + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Resources &res = *_vm->_resources; + Screen &screen = *_vm->_screen; + Window &window1 = screen._windows[1]; + + if (screen._windows[2]._enabled || screen._windows[10]._enabled) + return; + if (!party._automapOn && !party._wizardEyeActive) { + // Draw the Might & Magic logo + res._globalSprites.draw(window1, 5, Common::Point(232, 9)); + return; + } + + int v, frame; + int frame2 = _overallFrame * 2; + bool eyeActive = party._wizardEyeActive; + if (party._automapOn) + party._wizardEyeActive = false; + + if (map._isOutdoors) { + res._globalSprites.draw(window1, 15, Common::Point(237, 12)); + + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 4); + frame = map.mazeDataCurrent()._surfaceTypes[v]; + + if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, frame, Common::Point(xp, yp)); + } + } + } + + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 4); + frame = map.mazeData()._wallTypes[v]; + + if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, frame + 16, Common::Point(xp, yp)); + } + } + } + + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 4); + + if (v != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, v + 32, Common::Point(xp, yp)); + } + } + } + + // Draw the direction arrow + res._globalSprites.draw(window1, party._mazeDirection + 1, + Common::Point(267, 36)); + } + else { + frame2 = (frame2 + 2) % 8; + + // First draw the default surface bases for each cell to show + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 0, 0xffff); + + if (v != INVALID_CELL && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, 0, Common::Point(xp, yp)); + } + } + } + + // Draw correct surface bases for revealed tiles + for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 0, 0xffff); + int surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; + + if (v != INVALID_CELL && map._currentSurfaceId && + (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, surfaceId + 36, Common::Point(xp, yp)); + } + } + } + + v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0); + if (v != INVALID_CELL && map._currentSurfaceId && + (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, + map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, + Common::Point(232, 9)); + } + + // Handle drawing surface sprites partially clipped at the left edge + for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x - 4, party._mazePosition.y + yDiff), + 0, 0xffff); + + if (v != INVALID_CELL && map._currentSurfaceId && + (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, + map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, + Common::Point(232, yp)); + } + } + + // Handle drawing surface sprites partially clipped at the top edge + for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, ++xDiff, xp += 8) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + 4), + 0, 0xffff); + + if (v != INVALID_CELL && map._currentSurfaceId && + (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, + map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, + Common::Point(xp, 9)); + } + } + + // + for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE; + ++idx, ++xDiff, xp += 10, yp -= 8) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x - 4, party._mazePosition.y - 3 + idx), + 12, 0xffff); + + switch (v) { + case 1: + frame = 18; + break; + case 3: + frame = 22; + break; + case 4: + case 13: + frame = 16; + break; + case 5: + case 8: + frame = 2; + break; + case 6: + frame = 30; + break; + case 7: + frame = 32; + break; + case 9: + frame = 24; + break; + case 10: + frame = 28; + break; + case 11: + frame = 14; + break; + case 12: + frame = frame2 + 4; + break; + case 14: + frame = 24; + break; + case 15: + frame = 26; + break; + default: + frame = -1; + break; + } + + if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) + map._tileSprites.draw(window1, frame, Common::Point(222, yp)); + + v = map.mazeLookup( + Common::Point(party._mazePosition.x - 3 + idx, party._mazePosition.y + 4), + 0); + + switch (v) { + case 1: + frame = 19; + break; + case 2: + frame = 35; + break; + case 3: + frame = 23; + break; + case 4: + case 13: + frame = 17; + break; + case 5: + case 8: + frame = 3; + break; + case 6: + frame = 31; + break; + case 7: + frame = 33; + break; + case 9: + frame = 21; + break; + case 10: + frame = 29; + break; + case 11: + frame = 15; + break; + case 12: + frame = frame2 + 5; + break; + case 14: + frame = 25; + break; + case 15: + frame = 27; + break; + default: + frame = -1; + break; + } + + if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) + map._tileSprites.draw(window1, frame, Common::Point(xp, 4)); + } + + // Draw the front/back walls of cells in the minimap + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; + ++rowNum, --yDiff, yp += 8) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; + ++colNum, ++xDiff, xp += 10) { + if (colNum == 4 && rowNum == 4) { + // Center of the minimap. Draw the direction arrow + res._globalSprites.draw(window1, party._mazeDirection + 1, + Common::Point(272, 40)); + } + + v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff, + party._mazePosition.y + yDiff), 12, 0xffff); + switch (v) { + case 1: + frame = 18; + break; + case 3: + frame = 22; + break; + case 4: + case 13: + frame = 16; + break; + case 5: + case 8: + frame = 2; + break; + case 6: + frame = 30; + break; + case 7: + frame = 32; + break; + case 9: + frame = 20; + break; + case 10: + frame = 28; + break; + case 11: + frame = 14; + break; + case 12: + frame = frame2 + 4; + break; + case 14: + frame = 24; + break; + case 15: + frame = 26; + break; + default: + frame = -1; + break; + } + + if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, frame, Common::Point(xp, yp)); + } + + v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff, + party._mazePosition.y + yDiff), 12, 0xffff); + switch (v) { + case 1: + frame = 19; + break; + case 2: + frame = 35; + break; + case 3: + frame = 23; + break; + case 4: + case 13: + frame = 17; + break; + case 5: + case 8: + frame = 3; + break; + case 6: + frame = 31; + break; + case 7: + frame = 33; + break; + case 9: + frame = 21; + break; + case 10: + frame = 29; + break; + case 11: + frame = 15; + break; + case 12: + frame = frame2 + 5; + break; + case 14: + frame = 25; + break; + case 15: + frame = 27; + break; + default: + frame = -1; + break; + } + + if (v == -1 && (map._currentSteppedOn || party._wizardEyeActive)) { + map._tileSprites.draw(window1, frame, Common::Point(xp, yp)); + } + } + } + + // Draw the top of blocked/wall cells on the map + for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { + for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { + v = map.mazeLookup( + Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), + 0, 0xffff); + + if (v == INVALID_CELL || (!map._currentSteppedOn && !party._wizardEyeActive)) { + map._tileSprites.draw(window1, 1, Common::Point(xp, yp)); + } + } + } + } + + // Draw outer rectangle around the automap + res._globalSprites.draw(window1, 6, Common::Point(223, 3)); + party._wizardEyeActive = eyeActive; +} + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 660d1b1340..4435310233 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -93,6 +93,8 @@ private: void fall(int v); void shake(int time); + + void drawMiniMap(); public: int _intrIndex1; Common::String _interfaceText; diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index a098800f28..4f408d18e2 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -4556,380 +4556,4 @@ void InterfaceMap::assembleBorder() { screen._windows[12].frame(); } -void InterfaceMap::drawMiniMap() { - Map &map = *_vm->_map; - Party &party = *_vm->_party; - Resources &res = *_vm->_resources; - Screen &screen = *_vm->_screen; - Window &window1 = screen._windows[1]; - - if (screen._windows[2]._enabled || screen._windows[10]._enabled) - return; - if (!party._automapOn && !party._wizardEyeActive) { - // Draw the Might & Magic logo - res._globalSprites.draw(window1, 5, Common::Point(232, 9)); - return; - } - - int v, frame; - int frame2 = _overallFrame * 2; - bool eyeActive = party._wizardEyeActive; - if (party._automapOn) - party._wizardEyeActive = false; - - if (map._isOutdoors) { - res._globalSprites.draw(window1, 15, Common::Point(237, 12)); - - for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { - for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), - 4); - frame = map.mazeDataCurrent()._surfaceTypes[v]; - - if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, frame, Common::Point(xp, yp)); - } - } - } - - for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { - for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), - 4); - frame = map.mazeData()._wallTypes[v]; - - if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, frame + 16, Common::Point(xp, yp)); - } - } - } - - for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { - for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), - 4); - - if (v != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, v + 32, Common::Point(xp, yp)); - } - } - } - - // Draw the direction arrow - res._globalSprites.draw(window1, party._mazeDirection + 1, - Common::Point(267, 36)); - } else { - frame2 = (frame2 + 2) % 8; - - // First draw the default surface bases for each cell to show - for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { - for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), - 0, 0xffff); - - if (v != INVALID_CELL && (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, 0, Common::Point(xp, yp)); - } - } - } - - // Draw correct surface bases for revealed tiles - for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { - for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), - 0, 0xffff); - int surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId]; - - if (v != INVALID_CELL && map._currentSurfaceId && - (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, surfaceId + 36, Common::Point(xp, yp)); - } - } - } - - v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0); - if (v != INVALID_CELL && map._currentSurfaceId && - (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, - map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, - Common::Point(232, 9)); - } - - // Handle drawing surface sprites partially clipped at the left edge - for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x - 4, party._mazePosition.y + yDiff), - 0, 0xffff); - - if (v != INVALID_CELL && map._currentSurfaceId && - (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, - map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, - Common::Point(232, yp)); - } - } - - // Handle drawing surface sprites partially clipped at the top edge - for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, ++xDiff, xp += 8) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + 4), - 0, 0xffff); - - if (v != INVALID_CELL && map._currentSurfaceId && - (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, - map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36, - Common::Point(xp, 9)); - } - } - - // - for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE; - ++idx, ++xDiff, xp += 10, yp -= 8) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x - 4, party._mazePosition.y - 3 + idx), - 12, 0xffff); - - switch (v) { - case 1: - frame = 18; - break; - case 3: - frame = 22; - break; - case 4: - case 13: - frame = 16; - break; - case 5: - case 8: - frame = 2; - break; - case 6: - frame = 30; - break; - case 7: - frame = 32; - break; - case 9: - frame = 24; - break; - case 10: - frame = 28; - break; - case 11: - frame = 14; - break; - case 12: - frame = frame2 + 4; - break; - case 14: - frame = 24; - break; - case 15: - frame = 26; - break; - default: - frame = -1; - break; - } - - if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) - map._tileSprites.draw(window1, frame, Common::Point(222, yp)); - - v = map.mazeLookup( - Common::Point(party._mazePosition.x - 3 + idx, party._mazePosition.y + 4), - 0); - - switch (v) { - case 1: - frame = 19; - break; - case 2: - frame = 35; - break; - case 3: - frame = 23; - break; - case 4: - case 13: - frame = 17; - break; - case 5: - case 8: - frame = 3; - break; - case 6: - frame = 31; - break; - case 7: - frame = 33; - break; - case 9: - frame = 21; - break; - case 10: - frame = 29; - break; - case 11: - frame = 15; - break; - case 12: - frame = frame2 + 5; - break; - case 14: - frame = 25; - break; - case 15: - frame = 27; - break; - default: - frame = -1; - break; - } - - if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) - map._tileSprites.draw(window1, frame, Common::Point(xp, 4)); - } - - // Draw the front/back walls of cells in the minimap - for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; - ++rowNum, --yDiff, yp += 8) { - for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; - ++colNum, ++xDiff, xp += 10) { - if (colNum == 4 && rowNum == 4) { - // Center of the minimap. Draw the direction arrow - res._globalSprites.draw(window1, party._mazeDirection + 1, - Common::Point(272, 40)); - } - - v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff, - party._mazePosition.y + yDiff), 12, 0xffff); - switch (v) { - case 1: - frame = 18; - break; - case 3: - frame = 22; - break; - case 4: - case 13: - frame = 16; - break; - case 5: - case 8: - frame = 2; - break; - case 6: - frame = 30; - break; - case 7: - frame = 32; - break; - case 9: - frame = 20; - break; - case 10: - frame = 28; - break; - case 11: - frame = 14; - break; - case 12: - frame = frame2 + 4; - break; - case 14: - frame = 24; - break; - case 15: - frame = 26; - break; - default: - frame = -1; - break; - } - - if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, frame, Common::Point(xp, yp)); - } - - v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff, - party._mazePosition.y + yDiff), 12, 0xffff); - switch (v) { - case 1: - frame = 19; - break; - case 2: - frame = 35; - break; - case 3: - frame = 23; - break; - case 4: - case 13: - frame = 17; - break; - case 5: - case 8: - frame = 3; - break; - case 6: - frame = 31; - break; - case 7: - frame = 33; - break; - case 9: - frame = 21; - break; - case 10: - frame = 29; - break; - case 11: - frame = 15; - break; - case 12: - frame = frame2 + 5; - break; - case 14: - frame = 25; - break; - case 15: - frame = 27; - break; - default: - frame = -1; - break; - } - - if (v == -1 && (map._currentSteppedOn || party._wizardEyeActive)) { - map._tileSprites.draw(window1, frame, Common::Point(xp, yp)); - } - } - } - - // Draw the top of blocked/wall cells on the map - for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) { - for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) { - v = map.mazeLookup( - Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff), - 0, 0xffff); - - if (v == INVALID_CELL || (!map._currentSteppedOn && !party._wizardEyeActive)) { - map._tileSprites.draw(window1, 1, Common::Point(xp, yp)); - } - } - } - } - - // Draw outer rectangle around the automap - res._globalSprites.draw(window1, 6, Common::Point(223, 3)); - party._wizardEyeActive = eyeActive; -} - } // End of namespace Xeen diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 3fe851b2e8..a0626249de 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -123,8 +123,6 @@ protected: void animate3d(); - void drawMiniMap(); - virtual void setup(); void drawMap(); -- cgit v1.2.3 From 74b4d91f4a5b68b2aa0ec2a46f76131ccf897535 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Feb 2015 14:10:37 -0500 Subject: XEEN: Implemented startFalling --- engines/xeen/combat.cpp | 4 + engines/xeen/combat.h | 2 + engines/xeen/interface.cpp | 247 +++++++++++++++++++++++++++++++++++++++++++-- engines/xeen/interface.h | 3 +- engines/xeen/map.cpp | 3 +- engines/xeen/party.cpp | 1 - engines/xeen/party.h | 1 - engines/xeen/scripts.cpp | 2 + engines/xeen/scripts.h | 2 +- 9 files changed, 249 insertions(+), 16 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 4d0add115a..582444d5e5 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -47,5 +47,9 @@ void Combat::doCombat() { error("TODO: doCombat"); } +void Combat::giveCharDamage(int damage, int v2, int v3) { + error("TODO: giveCharDamage"); +} + } // End of namespace Xeen diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index c5c7f0817b..505874264c 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -67,6 +67,8 @@ public: void clear(); void doCombat(); + + void giveCharDamage(int damage, int v2, int v3); }; } // End of namespace Xeen diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index f81e5186c7..8a35563ba1 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -569,7 +569,7 @@ void Interface::doStepCode() { // We can fly, we can.. oh wait, we can't! damage = 100; party._damageType = DT_PHYSICAL; - party._falling = true; + _falling = true; break; case SURFTYPE_DESERT: // Without navigation skills, simulate getting lost by adding extra time @@ -579,7 +579,7 @@ void Interface::doStepCode() { case SURFTYPE_CLOUD: if (!party._levitateActive) { party._damageType = DT_PHYSICAL; - party._falling = true; + _falling = true; damage = 100; } break; @@ -588,10 +588,10 @@ void Interface::doStepCode() { } if (_vm->_files->_isDarkCc && party._gameFlags[374]) { - party._falling = false; + _falling = false; } else { - if (party._falling) - doFalling(); + if (_falling) + startFalling(false); if ((party._mazePosition.x & 16) || (party._mazePosition.y & 16)) { if (map._isOutdoors) @@ -611,17 +611,233 @@ void Interface::doStepCode() { } } -void Interface::doFalling() { - // TODO +/** + * Start the party falling + */ +void Interface::startFalling(bool flag) { + Combat &combat = *_vm->_combat; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Scripts &scripts = *_vm->_scripts; + bool isDarkCc = _vm->_files->_isDarkCc; + + if (isDarkCc && party._gameFlags[374]) { + _falling = 0; + return; + } + + _falling = false; + draw3d(true); + _falling = 2; + draw3d(false); + + if (flag) { + if (!isDarkCc || party._fallMaze != 0) { + party._mazeId = party._fallMaze; + party._mazePosition = party._fallPosition; + } + } + + _falling = true; + map.load(party._mazeId); + if (flag) { + if (((party._mazePosition.x & 16) || (party._mazePosition.y & 16)) && + map._isOutdoors) { + map.getNewMaze(); + } + } + + if (isDarkCc) { + switch (party._mazeId - 25) { + case 0: + case 26: + case 27: + case 28: + case 29: + party._mazeId = 24; + party._mazePosition = Common::Point(11, 9); + break; + case 1: + case 30: + case 31: + case 32: + case 33: + party._mazeId = 12; + party._mazePosition = Common::Point(6, 15); + break; + case 2: + case 34: + case 35: + case 36: + case 37: + case 51: + case 52: + case 53: + party._mazeId = 15; + party._mazePosition = Common::Point(4, 12); + party._mazeDirection = DIR_SOUTH; + break; + case 40: + case 41: + party._mazeId = 14; + party._mazePosition = Common::Point(8, 3); + break; + case 44: + case 45: + party._mazeId = 1; + party._mazePosition = Common::Point(8, 7); + party._mazeDirection = DIR_NORTH; + break; + case 49: + party._mazeId = 12; + party._mazePosition = Common::Point(11, 13); + party._mazeDirection = DIR_SOUTH; + break; + case 57: + case 58: + case 59: + party._mazeId = 5; + party._mazePosition = Common::Point(12, 7); + party._mazeDirection = DIR_NORTH; + break; + case 60: + party._mazeId = 6; + party._mazePosition = Common::Point(12, 3); + party._mazeDirection = DIR_NORTH; + break; + default: + party._mazeId = 23; + party._mazePosition = Common::Point(12, 10); + party._mazeDirection = DIR_NORTH; + break; + } + } else { + if (party._mazeId > 89 && party._mazeId < 113) { + party._mazeId += 168; + } else { + switch (party._mazeId - 25) { + case 0: + party._mazeId = 89; + party._mazePosition = Common::Point(2, 14); + break; + case 1: + party._mazeId = 109; + party._mazePosition = Common::Point(13, 14); + break; + case 2: + party._mazeId = 112; + party._mazePosition = Common::Point(13, 3); + break; + case 3: + party._mazeId = 92; + party._mazePosition = Common::Point(2, 3); + break; + case 12: + case 13: + party._mazeId = 14; + party._mazePosition = Common::Point(10, 2); + break; + case 16: + case 17: + case 18: + party._mazeId = 4; + party._mazePosition = Common::Point(5, 14); + break; + case 20: + case 21: + case 22: + party._mazeId = 21; + party._mazePosition = Common::Point(9, 11); + break; + case 24: + case 25: + case 26: + party._mazeId = 1; + party._mazePosition = Common::Point(10, 4); + break; + case 28: + case 29: + case 30: + case 31: + party._mazeId = 26; + party._mazePosition = Common::Point(12, 10); + break; + case 32: + case 33: + case 34: + case 35: + party._mazeId = 3; + party._mazePosition = Common::Point(4, 9); + break; + case 36: + case 37: + case 38: + case 39: + party._mazeId = 16; + party._mazePosition = Common::Point(2, 7); + break; + case 40: + case 41: + case 42: + case 43: + party._mazeId = 23; + party._mazePosition = Common::Point(10, 9); + break; + case 44: + case 45: + case 46: + case 47: + party._mazeId = 13; + party._mazePosition = Common::Point(2, 10); + break; + case 103: + case 104: + map._loadDarkSide = false; + party._mazeId = 8; + party._mazePosition = Common::Point(11, 15); + party._mazeDirection = DIR_NORTH; + break; + case 105: + party._mazeId = 24; + party._mazePosition = Common::Point(11, 9); + break; + case 106: + party._mazeId = 12; + party._mazePosition = Common::Point(6, 15); + break; + case 107: + party._mazeId = 15; + party._mazePosition = Common::Point(4, 12); + break; + default: + party._mazeId = 29; + party._mazePosition = Common::Point(25, 21); + party._mazeDirection = DIR_NORTH; + break; + } + } + } + + _flipGround ^= 1; + draw3d(true); + int tempVal = scripts._v2; + scripts._v2 = 0; + combat.giveCharDamage(party._fallDamage, 0, 0); + scripts._v2 = tempVal; + + _flipGround ^= 1; } +/** + * Check movement in the given direction + */ bool Interface::checkMoveDirection(int key) { Map &map = *_vm->_map; Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; Direction dir = party._mazeDirection; - switch (_buttonValue) { + switch (key) { case (Common::KBD_CTRL << 16) | Common::KEYCODE_LEFT: party._mazeDirection = (party._mazeDirection == DIR_NORTH) ? DIR_WEST : (Direction)(party._mazeDirection - 1); @@ -948,10 +1164,10 @@ void Interface::draw3d(bool updateFlag) { // Draw the minimap drawMiniMap(); - if (party._falling == 1) + if (_falling == 1) handleFalling(); - if (party._falling == 2) { + if (_falling == 2) { screen.saveBackground(1); } @@ -991,6 +1207,9 @@ void Interface::draw3d(bool updateFlag) { events.wait(2); } +/** + * Handle doing the falling + */ void Interface::handleFalling() { Party &party = *_vm->_party; Screen &screen = *_vm->_screen; @@ -1043,17 +1262,23 @@ void Interface::handleFalling() { } void Interface::saveFall() { - + // TODO } void Interface::fall(int v) { } +/** + * Shake the screen + */ void Interface::shake(int time) { } +/** + * Draw the minimap + */ void Interface::drawMiniMap() { Map &map = *_vm->_map; Party &party = *_vm->_party; diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 4435310233..e4278459af 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -98,6 +98,7 @@ private: public: int _intrIndex1; Common::String _interfaceText; + int _falling; public: Interface(XeenEngine *vm); @@ -111,7 +112,7 @@ public: void mainIconsPrint(); - void doFalling(); + void startFalling(bool v); void perform(); diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index dc58c2db6d..1c7cbd8a39 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -886,11 +886,12 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { } void Map::load(int mapId) { + Interface &intf = *_vm->_interface; Screen &screen = *_vm->_screen; IndoorDrawList &indoorList = _vm->_interface->_indoorList; OutdoorDrawList &outdoorList = _vm->_interface->_outdoorList; - if (_vm->_party->_falling) { + if (intf._falling) { Window &w = screen._windows[9]; w.open(); w.writeString(OOPS); diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index cd1dc21264..2eb4cc2027 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -111,7 +111,6 @@ Party::Party(XeenEngine *vm) { _isNight = false; _stepped = false; _damageType = DT_PHYSICAL; - _falling = false; _fallMaze = 0; _fallDamage = 0; _dead = false; diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 58bfbd2c39..4f32cca243 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -121,7 +121,6 @@ public: bool _newDay; bool _isNight; bool _stepped; - int _falling; Common::Point _fallPosition; int _fallMaze; int _fallDamage; diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 6ab4c1fe13..086c0d436a 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -804,10 +804,12 @@ void Scripts::cmdExchObj(Common::Array<byte> ¶ms) { } void Scripts::cmdFallToMap(Common::Array<byte> ¶ms) { + Interface &intf = *_vm->_interface; Party &party = *_vm->_party; party._fallMaze = params[0]; party._fallPosition = Common::Point(params[1], params[2]); party._fallDamage = params[3]; + intf.startFalling(true); _lineNum = -1; } diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index d353581497..cc32a9667f 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -148,7 +148,6 @@ private: int _mirrorId; int _refreshIcons; int _scriptResult; - int _v2; bool _scriptExecuted; bool _var50; MazeEvent *_event; @@ -229,6 +228,7 @@ public: int _whoWill; int _nEdamageType; int _itemType; + int _v2; Common::Array<MirrorEntry> _mirror; public: Scripts(XeenEngine *vm); -- cgit v1.2.3 From adde24a338eafc5aab0c3e51c439aea64bfdbfb7 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Feb 2015 14:20:35 -0500 Subject: XEEN: Move more code from InterfaceMap that should be in Interface class --- engines/xeen/interface.cpp | 119 ++++++++++++++++++++++++++++++++++++++++- engines/xeen/interface.h | 8 ++- engines/xeen/interface_map.cpp | 117 ---------------------------------------- engines/xeen/interface_map.h | 8 --- 4 files changed, 125 insertions(+), 127 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 8a35563ba1..0d488d1645 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -153,7 +153,11 @@ void Interface::initDrawStructs() { } void Interface::setup() { - InterfaceMap::setup(); + _borderSprites.load("border.icn"); + _spellFxSprites.load("spellfx.icn"); + _fecpSprites.load("fecp.brd"); + _blessSprites.load("bless.icn"); + _charPowSprites.load("charpow.icn"); _uiSprites.load("inn.icn"); Party &party = *_vm->_party; @@ -1656,4 +1660,117 @@ void Interface::drawMiniMap() { party._wizardEyeActive = eyeActive; } +/** + * Draw the display borders + */ +void Interface::assembleBorder() { + Resources &res = *_vm->_resources; + Screen &screen = *_vm->_screen; + + // Draw the outer frame + res._globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8)); + + // Draw the animating bat character used to show when levitate is active + _borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16, + Common::Point(0, 82)); + _batUIFrame = (_batUIFrame + 1) % 12; + + // Draw UI element to indicate whether can spot hidden doors + _borderSprites.draw(screen, + (_thinWall && _vm->_party->checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, + Common::Point(194, 91)); + _spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12; + + // Draw UI element to indicate whether can sense danger + _borderSprites.draw(screen, + (_vm->_dangerSenseAllowed && _vm->_party->checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40, + Common::Point(107, 9)); + _dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12; + + // Handle the face UI elements for indicating clairvoyance status + _face1UIFrame = (_face1UIFrame + 1) % 4; + if (_face1State == 0) + _face1UIFrame += 4; + else if (_face1State == 2) + _face1UIFrame = 0; + + _face2UIFrame = (_face2UIFrame + 1) % 4 + 12; + if (_face2State == 0) + _face2UIFrame += 252; + else if (_face2State == 2) + _face2UIFrame = 0; + + if (!_vm->_party->_clairvoyanceActive) { + _face1UIFrame = 0; + _face2UIFrame = 8; + } + + _borderSprites.draw(screen, _face1UIFrame, Common::Point(0, 32)); + _borderSprites.draw(screen, + screen._windows[10]._enabled || screen._windows[2]._enabled ? + 52 : _face2UIFrame, + Common::Point(215, 32)); + + // Draw resistence indicators + if (!screen._windows[10]._enabled && !screen._windows[2]._enabled + && screen._windows[38]._enabled) { + _fecpSprites.draw(screen, _vm->_party->_fireResistence ? 1 : 0, + Common::Point(2, 2)); + _fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 3 : 2, + Common::Point(219, 2)); + _fecpSprites.draw(screen, _vm->_party->_coldResistence ? 5 : 4, + Common::Point(2, 134)); + _fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 7 : 6, + Common::Point(219, 134)); + } else { + _fecpSprites.draw(screen, _vm->_party->_fireResistence ? 9 : 8, + Common::Point(8, 8)); + _fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 10 : 11, + Common::Point(219, 8)); + _fecpSprites.draw(screen, _vm->_party->_coldResistence ? 12 : 13, + Common::Point(8, 134)); + _fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 14 : 15, + Common::Point(219, 134)); + } + + // Draw UI element for blessed + _blessSprites.draw(screen, 16, Common::Point(33, 137)); + if (_vm->_party->_blessed) { + _blessedUIFrame = (_blessedUIFrame + 1) % 4; + _blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137)); + } + + // Draw UI element for power shield + if (_vm->_party->_powerShield) { + _powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4; + _blessSprites.draw(screen, _powerShieldUIFrame + 4, + Common::Point(55, 137)); + } + + // Draw UI element for holy bonus + if (_vm->_party->_holyBonus) { + _holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4; + _blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137)); + } + + // Draw UI element for heroism + if (_vm->_party->_heroism) { + _heroismUIFrame = (_heroismUIFrame + 1) % 4; + _blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137)); + } + + // Draw direction character if direction sense is active + if (_vm->_party->checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) { + const char *dirText = DIRECTION_TEXT_UPPER[_vm->_party->_mazeDirection]; + Common::String msg = Common::String::format( + "\002""08\003""c\013""139\011""116%c\014""d\001", *dirText); + screen._windows[0].writeString(msg); + } + + // Draw view frame + if (screen._windows[12]._enabled) + screen._windows[12].frame(); +} + + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index e4278459af..8d3044fd72 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -64,6 +64,10 @@ private: XeenEngine *_vm; SpriteResource _uiSprites; SpriteResource _iconSprites; + SpriteResource _borderSprites; + SpriteResource _spellFxSprites; + SpriteResource _fecpSprites; + SpriteResource _blessSprites; DrawStruct _mainList[16]; int _combatCharIds[8]; @@ -104,7 +108,7 @@ public: virtual ~Interface() {} - virtual void setup(); + void setup(); void manageCharacters(bool soundPlayed); @@ -121,6 +125,8 @@ public: void bash(const Common::Point &pt, Direction direction); void draw3d(bool updateFlag); + + void assembleBorder(); }; } // End of namespace Xeen diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 4f408d18e2..837971b2fb 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -398,14 +398,6 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) { _face1State = _face2State = 0; } -void InterfaceMap::setup() { - _borderSprites.load("border.icn"); - _spellFxSprites.load("spellfx.icn"); - _fecpSprites.load("fecp.brd"); - _blessSprites.load("bless.icn"); - _charPowSprites.load("charpow.icn"); -} - void InterfaceMap::drawMap() { Combat &combat = *_vm->_combat; Map &map = *_vm->_map; @@ -4447,113 +4439,4 @@ void InterfaceMap::moveMonsters() { // TODO } -void InterfaceMap::assembleBorder() { - Resources &res = *_vm->_resources; - Screen &screen = *_vm->_screen; - - // Draw the outer frame - res._globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8)); - - // Draw the animating bat character used to show when levitate is active - _borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16, - Common::Point(0, 82)); - _batUIFrame = (_batUIFrame + 1) % 12; - - // Draw UI element to indicate whether can spot hidden doors - _borderSprites.draw(screen, - (_thinWall && _vm->_party->checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28, - Common::Point(194, 91)); - _spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12; - - // Draw UI element to indicate whether can sense danger - _borderSprites.draw(screen, - (_vm->_dangerSenseAllowed && _vm->_party->checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40, - Common::Point(107, 9)); - _dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12; - - // Handle the face UI elements for indicating clairvoyance status - _face1UIFrame = (_face1UIFrame + 1) % 4; - if (_face1State == 0) - _face1UIFrame += 4; - else if (_face1State == 2) - _face1UIFrame = 0; - - _face2UIFrame = (_face2UIFrame + 1) % 4 + 12; - if (_face2State == 0) - _face2UIFrame += 252; - else if (_face2State == 2) - _face2UIFrame = 0; - - if (!_vm->_party->_clairvoyanceActive) { - _face1UIFrame = 0; - _face2UIFrame = 8; - } - - _borderSprites.draw(screen, _face1UIFrame, Common::Point(0, 32)); - _borderSprites.draw(screen, - screen._windows[10]._enabled || screen._windows[2]._enabled ? - 52 : _face2UIFrame, - Common::Point(215, 32)); - - // Draw resistence indicators - if (!screen._windows[10]._enabled && !screen._windows[2]._enabled - && screen._windows[38]._enabled) { - _fecpSprites.draw(screen, _vm->_party->_fireResistence ? 1 : 0, - Common::Point(2, 2)); - _fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 3 : 2, - Common::Point(219, 2)); - _fecpSprites.draw(screen, _vm->_party->_coldResistence ? 5 : 4, - Common::Point(2, 134)); - _fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 7 : 6, - Common::Point(219, 134)); - } else { - _fecpSprites.draw(screen, _vm->_party->_fireResistence ? 9 : 8, - Common::Point(8, 8)); - _fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 10 : 11, - Common::Point(219, 8)); - _fecpSprites.draw(screen, _vm->_party->_coldResistence ? 12 : 13, - Common::Point(8, 134)); - _fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 14 : 15, - Common::Point(219, 134)); - } - - // Draw UI element for blessed - _blessSprites.draw(screen, 16, Common::Point(33, 137)); - if (_vm->_party->_blessed) { - _blessedUIFrame = (_blessedUIFrame + 1) % 4; - _blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137)); - } - - // Draw UI element for power shield - if (_vm->_party->_powerShield) { - _powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4; - _blessSprites.draw(screen, _powerShieldUIFrame + 4, - Common::Point(55, 137)); - } - - // Draw UI element for holy bonus - if (_vm->_party->_holyBonus) { - _holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4; - _blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137)); - } - - // Draw UI element for heroism - if (_vm->_party->_heroism) { - _heroismUIFrame = (_heroismUIFrame + 1) % 4; - _blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137)); - } - - // Draw direction character if direction sense is active - if (_vm->_party->checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) { - const char *dirText = DIRECTION_TEXT_UPPER[_vm->_party->_mazeDirection]; - Common::String msg = Common::String::format( - "\002""08\003""c\013""139\011""116%c\014""d\001", *dirText); - screen._windows[0].writeString(msg); - } - - // Draw view frame - if (screen._windows[12]._enabled) - screen._windows[12].frame(); -} - } // End of namespace Xeen diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index a0626249de..9ac9222b67 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -92,10 +92,6 @@ public: class InterfaceMap { private: XeenEngine *_vm; - SpriteResource _borderSprites; - SpriteResource _spellFxSprites; - SpriteResource _fecpSprites; - SpriteResource _blessSprites; int _combatFloatCounter; void initDrawStructs(); @@ -123,8 +119,6 @@ protected: void animate3d(); - virtual void setup(); - void drawMap(); public: OutdoorDrawList _outdoorList; @@ -160,8 +154,6 @@ public: void drawOutdoors(); - void assembleBorder(); - void moveMonsters(); }; -- cgit v1.2.3 From 93e5fd7c20a69a052625293133d7d93728444c3b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Feb 2015 14:43:04 -0500 Subject: XEEN: Moved more variables out of InterfaceMap that belong in Interface --- engines/xeen/interface.cpp | 28 ++++++++++++++++++++++++++-- engines/xeen/interface.h | 15 +++++++++++++++ engines/xeen/interface_map.cpp | 27 --------------------------- engines/xeen/interface_map.h | 17 ----------------- 4 files changed, 41 insertions(+), 46 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 0d488d1645..cebd14d6a0 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -127,12 +127,25 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _buttonsLoaded = false; _intrIndex1 = 0; _steppingFX = 0; + _falling = false; + _blessedUIFrame = 0; + _powerShieldUIFrame = 0; + _holyBonusUIFrame = 0; + _heroismUIFrame = 0; + _flipUIFrame = 0; + _face1UIFrame = 0; + _face2UIFrame = 0; + _batUIFrame = 0; + _spotDoorsUIFrame = 0; + _dangerSenseUIFrame = 0; + _face1State = _face2State = 0; + _upDoorText = false; + _tillMove = 0; Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); initDrawStructs(); } - void Interface::initDrawStructs() { _mainList[0] = DrawStruct(7, 232, 74); _mainList[1] = DrawStruct(0, 235, 75); @@ -1162,6 +1175,15 @@ void Interface::draw3d(bool updateFlag) { if (screen._windows[11]._enabled) return; + _flipUIFrame = (_flipUIFrame + 1) % 4; + if (_flipUIFrame == 0) + _flipWater = !_flipWater; + if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_COMBAT) && + !_flag1 && _vm->_moveMonsters) { + if (--_tillMove == 0) + moveMonsters(); + } + // Draw the map drawMap(); @@ -1200,7 +1222,6 @@ void Interface::draw3d(bool updateFlag) { party._stepped = false; if (_vm->_mode == MODE_9) { // TODO: Save current scripts data? - error("TODO: save scripts?"); } // TODO: Check use of updateFlag here. Original doesn't have it, but I @@ -1772,5 +1793,8 @@ void Interface::assembleBorder() { screen._windows[12].frame(); } +void Interface::moveMonsters() { + // TODO +} } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 8d3044fd72..fa5f1aaec1 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -73,6 +73,11 @@ private: bool _buttonsLoaded; int _steppingFX; + int _blessedUIFrame; + int _powerShieldUIFrame; + int _holyBonusUIFrame; + int _heroismUIFrame; + int _flipUIFrame; void initDrawStructs(); @@ -103,6 +108,14 @@ public: int _intrIndex1; Common::String _interfaceText; int _falling; + int _face1State, _face2State; + int _face1UIFrame, _face2UIFrame; + int _spotDoorsUIFrame; + int _dangerSenseUIFrame; + int _batUIFrame; + bool _upDoorText; + Common::String _screenText; + byte _tillMove; public: Interface(XeenEngine *vm); @@ -127,6 +140,8 @@ public: void draw3d(bool updateFlag); void assembleBorder(); + + void moveMonsters(); }; } // End of namespace Xeen diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 837971b2fb..6f4f708382 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -381,21 +381,8 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) { _combatFloatCounter = 0; _thinWall = false; _isAnimReset = false; - _upDoorText = false; - _batUIFrame = 0; - _spotDoorsUIFrame = 0; - _dangerSenseUIFrame = 0; - _face1UIFrame = 0; - _face2UIFrame = 0; - _blessedUIFrame = 0; - _powerShieldUIFrame = 0; - _holyBonusUIFrame = 0; - _heroismUIFrame = 0; - _flipUIFrame = 0; - _tillMove = 0; _flag1 = false; _overallFrame = 0; - _face1State = _face2State = 0; } void InterfaceMap::drawMap() { @@ -408,15 +395,6 @@ void InterfaceMap::drawMap() { const int OUTDOOR_INDEXES[3] = { 119, 113, 116 }; const int COMBAT_OFFSET_X[4] = { 8, 6, 4, 2 }; - _flipUIFrame = (_flipUIFrame + 1) % 4; - if (_flipUIFrame == 0) - _flipWater = !_flipWater; - if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_COMBAT) && - !_flag1 && _vm->_moveMonsters) { - if (--_tillMove == 0) - moveMonsters(); - } - MazeObject &objObject = map._mobData._objects[_objNumber]; Direction partyDirection = _vm->_party->_mazeDirection; int objNum = _objNumber - 1; @@ -4434,9 +4412,4 @@ void InterfaceMap::drawOutdoors() { _charsShooting = _isShooting; } - -void InterfaceMap::moveMonsters() { - // TODO -} - } // End of namespace Xeen diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 9ac9222b67..761e99760c 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -88,7 +88,6 @@ public: int size() const { return 170; } }; - class InterfaceMap { private: XeenEngine *_vm; @@ -108,11 +107,6 @@ protected: bool _isShooting; bool _thinWall; bool _isAnimReset; - int _blessedUIFrame; - int _powerShieldUIFrame; - int _holyBonusUIFrame; - int _heroismUIFrame; - int _flipUIFrame; bool _flag1; void setMazeBits(); @@ -124,16 +118,8 @@ public: OutdoorDrawList _outdoorList; IndoorDrawList _indoorList; SpriteResource _charPowSprites; - bool _upDoorText; - Common::String _screenText; - int _face1State, _face2State; - int _face1UIFrame, _face2UIFrame; - int _spotDoorsUIFrame; - int _dangerSenseUIFrame; - byte _tillMove; int _objNumber; int _overallFrame; - int _batUIFrame; bool _charsShooting; public: InterfaceMap(XeenEngine *vm); @@ -153,9 +139,6 @@ public: void setOutdoorsObjects(); void drawOutdoors(); - - void moveMonsters(); - }; } // End of namespace Xeen -- cgit v1.2.3 From bdc8e73c1bbd3fc8c29b48028d02d1d4950f08a3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Feb 2015 14:55:59 -0500 Subject: XEEN: Fix walking through walls --- engines/xeen/interface.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index cebd14d6a0..cac9f3a62d 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -923,6 +923,8 @@ bool Interface::checkMoveDirection(int key) { int surfaceId = map.getCell(2); if (surfaceId >= map.mazeData()._difficulties._wallNoPass) { party._mazeDirection = dir; + sound.playFX(46); + return false; } else { party._mazeDirection = dir; -- cgit v1.2.3 From ef2a4595c2c17260f61ad93d6c4374af7fa8a606 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Feb 2015 15:01:22 -0500 Subject: XEEN: Moved _openDoor into InterfaceMap --- engines/xeen/interface.cpp | 4 ++-- engines/xeen/interface_map.cpp | 5 +++-- engines/xeen/interface_map.h | 1 + engines/xeen/xeen.cpp | 1 - engines/xeen/xeen.h | 1 - 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index cac9f3a62d..11fc3127cf 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -934,10 +934,10 @@ bool Interface::checkMoveDirection(int key) { return false; } else { if (_buttonValue == Common::KEYCODE_UP && _wo[107]) { - _vm->_openDoor = true; + _openDoor = true; sound.playFX(47); draw3d(true); - _vm->_openDoor = false; + _openDoor = false; } return true; } diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 6f4f708382..a3241a133f 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -383,6 +383,7 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) { _isAnimReset = false; _flag1 = false; _overallFrame = 0; + _openDoor = false; } void InterfaceMap::drawMap() { @@ -4243,7 +4244,7 @@ void InterfaceMap::drawIndoors() { if (_wo[107]) { _indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2; - if (!_vm->_openDoor) + if (!_openDoor) _indoorList._fwl_1F1R._frame = 0; else _indoorList._fwl_1F1R._frame = map.mazeData()._wallKind ? 1 : 10; @@ -4303,7 +4304,7 @@ void InterfaceMap::drawIndoors() { _indoorList[0]._sprites = &map._skySprites[map._currentSky]; _indoorList[0]._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0; - if (_vm->_openDoor) { + if (_openDoor) { Common::Point pt( _vm->_party->_mazePosition.x + SCREEN_POSITIONING_X[ _vm->_party->_mazeDirection][_vm->_party->_mazePosition.x], diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 761e99760c..1ff982972f 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -121,6 +121,7 @@ public: int _objNumber; int _overallFrame; bool _charsShooting; + bool _openDoor; public: InterfaceMap(XeenEngine *vm); diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index e0a2bebacd..a3240bf8b5 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -56,7 +56,6 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _noDirectionSense = false; _moveMonsters = false; _mode = MODE_0; - _openDoor = 0; _startupWindowActive = false; } diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 2d85335ced..d0a72f5868 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -157,7 +157,6 @@ public: bool _dangerSenseAllowed; bool _noDirectionSense; bool _moveMonsters; - int _openDoor; bool _startupWindowActive; public: XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); -- cgit v1.2.3 From 75a070de1755fca9244eec1796ea892118afa84b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Feb 2015 20:47:56 -0500 Subject: XEEN: Implementing combat methods --- engines/xeen/combat.cpp | 401 ++++++++++++++++++++++++++++++++++++++++- engines/xeen/combat.h | 31 +++- engines/xeen/dialogs_items.cpp | 2 +- engines/xeen/interface.cpp | 20 +- engines/xeen/interface.h | 3 - engines/xeen/interface_map.cpp | 69 ++++--- engines/xeen/interface_map.h | 19 +- 7 files changed, 481 insertions(+), 64 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 582444d5e5..3797c18139 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -20,12 +20,64 @@ * */ -#include "xeen/combat.h" #include "common/algorithm.h" -#include "common/textconsole.h" +#include "common/rect.h" +#include "xeen/combat.h" +#include "xeen/interface.h" +#include "xeen/xeen.h" namespace Xeen { +static const int MONSTER_GRID_X[48] = { + 1, 1, 1, 0, -1, -1, -1, 1, 1, 1, 0, -1, + -1, -1, 1, 1, 1, 0, -1, -1, -1, 1, 1, 1, + 0, -1, -1, -1, 1, 1, 1, 0, -1, -1, -1, 1, + 1, 1, 0, -1, -1, -1, 1, 1, 1, 0, -1, -1 +}; + +static const int MONSTER_GRID_Y[48] = { + 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, + 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0 +}; + +static const int MONSTER_GRID3[48] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + - 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, + 0, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static const int MONSTER_GRID_BITINDEX1[48] = { + 1, 1, 1, 2, 3, 3, 3, 1, 1, 1, 2, 3, + 3, 3, 1, 1, 1, 2, 3, 3, 3, 1, 1, 1, + 0, 3, 3, 3, 1, 1, 1, 0, 3, 3, 3, 1, + 1, 1, 0, 3, 3, 3, 1, 1, 1, 0, 3, 3 +}; + +static const int MONSTER_GRID_BITINDEX2[48] = { + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, + 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const int MONSTER_GRID_BITMASK[12] = { + 0xC, 8, 4, 0, 0xF, 0xF000, 0xF00, 0xF0, 0xF00, 0xF0, 0x0F, 0xF000 +}; + +static const int ATTACK_TYPE_FX[23] = { + 49, 18, 13, 14, 15, 17, 16, 0, 6, 1, 2, 3, + 4, 5, 4, 9, 27, 29, 44, 51, 53, 61, 71 +}; + +static const int MONSTER_SHOOT_POW[7] = { 12, 14, 0, 4, 8, 10, 13 }; + +static const int COMBAT_SHOOTING[4] = { 1, 1, 2, 3 }; + +/*------------------------------------------------------------------------*/ + Combat::Combat(XeenEngine *vm): _vm(vm) { Common::fill(&_attackMonsters[0], &_attackMonsters[26], 0); Common::fill(&_charsArray1[0], &_charsArray1[12], 0); @@ -34,9 +86,14 @@ Combat::Combat(XeenEngine *vm): _vm(vm) { Common::fill(&_elemPow[0], &_elemPow[12], 0); Common::fill(&_elemScale[0], &_elemScale[12], 0); Common::fill(&_shooting[0], &_shooting[8], 0); + Common::fill(&_monsterMap[0][0], &_monsterMap[32][32], 0); + Common::fill(&_monsterMoved[0], &_monsterMoved[MAX_NUM_MONSTERS], false); + Common::fill(&_rangeAttacking[0], &_rangeAttacking[MAX_NUM_MONSTERS], false); + Common::fill(&_gmonHit[0], &_gmonHit[36], 0); _globalCombat = 0; _whosTurn = -1; _itemFlag = false; + _monstersAttacking = false; } void Combat::clear() { @@ -51,5 +108,345 @@ void Combat::giveCharDamage(int damage, int v2, int v3) { error("TODO: giveCharDamage"); } +void Combat::moveMonsters() { + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + + if (!_vm->_moveMonsters) + return; + + intf._tillMove = 0; + if (intf._charsShooting) + return; + + Common::fill(&_monsterMap[0][0], &_monsterMap[32][32], 0); + Common::fill(&_monsterMoved[0], &_monsterMoved[MAX_NUM_MONSTERS], false); + Common::fill(&_rangeAttacking[0], &_rangeAttacking[MAX_NUM_MONSTERS], false); + Common::fill(&_gmonHit[0], &_gmonHit[36], -1); + _vm->_dangerSenseAllowed = false; + + for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) { + MazeMonster &monster = map._mobData._monsters[idx]; + if (monster._position.y < 32) { + _monsterMap[monster._position.y][monster._position.x]++; + } + } + + for (int loopNum = 0; loopNum < 2; ++loopNum) { + int arrIndex = -1; + for (int yDiff = 3; yDiff >= -3; --yDiff) { + for (int xDiff = 3; xDiff >= -3; --xDiff) { + Common::Point pt = party._mazePosition + Common::Point(xDiff, yDiff); + ++arrIndex; + + for (int idx = 0; idx < (int)map._mobData._monsters.size(); ++idx) { + MazeMonster &monster = map._mobData._monsters[idx]; + MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + + if (pt == monster._position) { + _vm->_dangerSenseAllowed = true; + if ((monster._isAttacking || _vm->_mode == MODE_SLEEPING) + && !_monsterMoved[idx]) { + if (party._mazePosition.x == pt.x || party._mazePosition.y == pt.y) { + // Check for range attacks + if (monsterData._rangeAttack && !_rangeAttacking[idx] + && _attackMonsters[0] != idx && _attackMonsters[1] != idx + && _attackMonsters[2] != idx && !monster._field7) { + // Setup monster for attacking + setupMonsterAttack(monster._spriteId, pt); + _rangeAttacking[idx] = true; + } + } + } + } + + switch (party._mazeDirection) { + case DIR_NORTH: + case DIR_SOUTH: + if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]], + MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) { + // Move the monster + moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex])); + } else { + if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]], + arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0, + arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex], + idx)) + if (arrIndex >= 21 && arrIndex <= 27) { + moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0)); + } else { + moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex])); + } + } + break; + + case DIR_EAST: + case DIR_WEST: + if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]], + arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0, + arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex], + idx)) { + if (arrIndex >= 21 && arrIndex <= 27) { + moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0)); + } else { + moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex])); + } + } else if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]], + MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) { + moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex])); + } + } + } + } + } + } + + monsterOvercome(); + if (_monstersAttacking) + monstersAttack(); +} + +void Combat::monstersAttack() { + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + int powNum = -1; + MonsterStruct *monsterData = nullptr; + OutdoorDrawList &outdoorList = intf._outdoorList; + IndoorDrawList &indoorList = intf._indoorList; + + for (int idx = 0; idx < 36; ++idx) { + if (_gmonHit[idx] != -1) { + monsterData = &map._monsterData[_gmonHit[idx]]; + powNum = MONSTER_SHOOT_POW[monsterData->_attackType]; + if (powNum != 12) + break; + } + } + + _powSprites.load(Common::String::format("pow%d.icn", powNum)); + sound.playFX(ATTACK_TYPE_FX[monsterData->_attackType]); + + for (int charNum = 0; charNum < MAX_PARTY_COUNT; ++charNum) { + if (!_shooting[charNum]) + continue; + + if (map._isOutdoors) { + outdoorList._attackImgs1[charNum]._scale = 3; + outdoorList._attackImgs2[charNum]._scale = 7; + outdoorList._attackImgs3[charNum]._scale = 11; + outdoorList._attackImgs4[charNum]._scale = 15; + outdoorList._attackImgs1[charNum]._sprites = nullptr; + outdoorList._attackImgs2[charNum]._sprites = nullptr; + outdoorList._attackImgs3[charNum]._sprites = nullptr; + outdoorList._attackImgs4[charNum]._sprites = nullptr; + + switch (_shooting[charNum]) { + case 1: + outdoorList._attackImgs1[charNum]._sprites = &_powSprites; + break; + case 2: + outdoorList._attackImgs2[charNum]._sprites = &_powSprites; + break; + default: + outdoorList._attackImgs3[charNum]._sprites = &_powSprites; + break; + } + } else { + indoorList._attackImgs1[charNum]._scale = 3; + indoorList._attackImgs2[charNum]._scale = 7; + indoorList._attackImgs3[charNum]._scale = 11; + indoorList._attackImgs4[charNum]._scale = 15; + indoorList._attackImgs1[charNum]._sprites = nullptr; + indoorList._attackImgs2[charNum]._sprites = nullptr; + indoorList._attackImgs3[charNum]._sprites = nullptr; + indoorList._attackImgs4[charNum]._sprites = nullptr; + + switch (_shooting[charNum]) { + case 1: + indoorList._attackImgs1[charNum]._sprites = &_powSprites; + break; + case 2: + indoorList._attackImgs2[charNum]._sprites = &_powSprites; + break; + default: + indoorList._attackImgs3[charNum]._sprites = &_powSprites; + break; + } + } + } + + // Wait whilst the attacking effect is done + do { + intf.draw3d(true); + events.pollEventsAndWait(); + } while (!_vm->shouldQuit() && intf._isAttacking); + + endAttack(); + + if (_vm->_mode != MODE_COMBAT) { + // Combat wasn't previously active, but it is now. Set up + // the combat party from the currently active party + party._combatParty.clear(); + for (uint idx = 0; idx < party._activeParty.size(); ++idx) + party._combatParty.push_back(&party._activeParty[idx]); + } + + for (int idx = 0; idx < 36; ++idx) { + if (_gmonHit[idx] != -1) + attackMonster(_gmonHit[idx]); + } + + _monstersAttacking = false; + + if (_vm->_mode != MODE_SLEEPING) { + for (uint charNum = 0; charNum < party._activeParty.size(); ++charNum) { + Condition condition = party._activeParty[charNum].worstCondition(); + + if (condition != ASLEEP && (condition < PARALYZED || condition == NO_CONDITION)) { + _vm->_mode = MODE_1; + break; + } + } + } +} + +void Combat::setupMonsterAttack(int monsterDataIndex, const Common::Point &pt) { + Party &party = *_vm->_party; + + for (int idx = 0; idx < 36; ++idx) { + if (_gmonHit[idx] != -1) { + int result = stopAttack(pt - party._mazePosition); + if (result) { + _monstersAttacking = true; + _gmonHit[idx] = monsterDataIndex; + + if (result != 1) { + for (int charNum = 0; charNum < MAX_PARTY_COUNT; ++charNum) { + if (!_shooting[charNum]) { + _shooting[charNum] = COMBAT_SHOOTING[result - 1]; + } + } + } + } + } + } +} + +bool Combat::monsterCanMove(const Common::Point &pt, int wallShift, + int xDiff, int yDiff, int monsterId) { + Map &map = *_vm->_map; + MazeMonster &monster = map._mobData._monsters[monsterId]; + MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + + Common::Point tempPos = pt; + if (map._isOutdoors) { + tempPos += Common::Point(xDiff, yDiff); + wallShift = 4; + } + int v = map.mazeLookup(tempPos, wallShift); + + if (!map._isOutdoors) { + return v <= map.mazeData()._difficulties._wallNoPass; + } else { + SurfaceType surfaceType; + switch (v) { + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 8: + case 11: + case 13: + case 14: + surfaceType = (SurfaceType)map.mazeData()._surfaceTypes[map._currentSurfaceId]; + if (surfaceType == SURFTYPE_WATER || surfaceType == SURFTYPE_DWATER) { + return monsterData._flying || monster._spriteId == 59; + } else if (surfaceType == SURFTYPE_SPACE) { + return monsterData._flying; + } else { + return _vm->_files->_isDarkCc || monster._spriteId != 59; + } + default: + return v <= map.mazeData()._difficulties._wallNoPass; + } + } +} + +void Combat::moveMonster(int monsterId, const Common::Point &pt) { + Map &map = *_vm->_map; + MazeMonster &monster = map._mobData._monsters[monsterId]; + + if (_monsterMap[pt.y][pt.x] < 3 && !monster._field7 && _vm->_moveMonsters) { + ++_monsterMap[pt.y][pt.x]; + --_monsterMap[monster._position.y][monster._position.x]; + monster._position = pt; + _monsterMoved[monsterId] = true; + } +} + +void Combat::endAttack() { + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + intf._isAttacking = false; + IndoorDrawList &indoorList = intf._indoorList; + OutdoorDrawList &outdoorList = intf._outdoorList; + + for (uint idx = 0; idx < party._activeParty.size(); ++idx) { + Character &c = party._activeParty[idx]; + + if (map._isOutdoors) { + outdoorList._attackImgs1[idx]._scale = 0; + outdoorList._attackImgs2[idx]._scale = 0; + outdoorList._attackImgs3[idx]._scale = 0; + outdoorList._attackImgs4[idx]._scale = 0; + outdoorList._attackImgs1[idx]._sprites = nullptr; + outdoorList._attackImgs2[idx]._sprites = nullptr; + outdoorList._attackImgs3[idx]._sprites = nullptr; + outdoorList._attackImgs4[idx]._sprites = nullptr; + } else { + indoorList._attackImgs1[idx]._scale = 0; + indoorList._attackImgs2[idx]._scale = 0; + indoorList._attackImgs3[idx]._scale = 0; + indoorList._attackImgs4[idx]._scale = 0; + indoorList._attackImgs1[idx]._sprites = nullptr; + indoorList._attackImgs2[idx]._sprites = nullptr; + indoorList._attackImgs3[idx]._sprites = nullptr; + indoorList._attackImgs4[idx]._sprites = nullptr; + } + } + + Common::fill(&_shooting[0], &_shooting[MAX_PARTY_COUNT], false); +} + +void Combat::monsterOvercome() { + Map &map = *_vm->_map; + + for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) { + MazeMonster &monster = map._mobData._monsters[idx]; + int dataIndex = monster._spriteId; + + if (monster._field7 != 0 && monster._field7 != 13) { + // Do a saving throw for monster + if (dataIndex <= _vm->getRandomNumber(1, dataIndex + 50)) + monster._field7 = 0; + } + } +} + +void Combat::attackMonster(int monsterId) { + +} + +bool Combat::stopAttack(const Common::Point &diffPt) { + // TODO + return false; +} } // End of namespace Xeen diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 505874264c..977d580047 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -24,9 +24,13 @@ #define XEEN_COMBAT_H #include "common/scummsys.h" +#include "common/rect.h" +#include "xeen/sprites.h" namespace Xeen { +#define MAX_NUM_MONSTERS 107 + enum DamageType { DT_PHYSICAL = 0, DT_MAGICAL = 1, DT_FIRE = 2, DT_ELECTRICAL = 3, DT_COLD = 4, DT_POISON = 5, DT_ENERGY = 6, DT_SLEEP = 7, @@ -51,16 +55,39 @@ class Combat { private: XeenEngine *_vm; public: + SpriteResource _powSprites; int _attackMonsters[26]; int _charsArray1[12]; bool _monPow[12]; int _monsterScale[12]; int _elemPow[12]; int _elemScale[12]; - bool _shooting[8]; + int _shooting[8]; int _globalCombat; int _whosTurn; bool _itemFlag; + int _monsterMap[32][32]; + bool _monsterMoved[MAX_NUM_MONSTERS]; + bool _rangeAttacking[MAX_NUM_MONSTERS]; + int _gmonHit[36]; + bool _monstersAttacking; + + void monstersAttack(); + + void setupMonsterAttack(int monsterDataIndex, const Common::Point &pt); + + bool monsterCanMove(const Common::Point &pt, int wallShift, + int v1, int v2, int monsterId); + + void moveMonster(int monsterId, const Common::Point &pt); + + void attackMonster(int monsterId); + + void endAttack(); + + void monsterOvercome(); + + bool stopAttack(const Common::Point &diffPt); public: Combat(XeenEngine *vm); @@ -69,6 +96,8 @@ public: void doCombat(); void giveCharDamage(int damage, int v2, int v3); + + void moveMonsters(); }; } // End of namespace Xeen diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index d37d124a7c..29ec4c684b 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -1052,7 +1052,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite } intf._charsShooting = false; - intf.moveMonsters(); + combat.moveMonsters(); combat._whosTurn = -1; return true; } diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 11fc3127cf..db0bd815aa 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -142,7 +142,6 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _upDoorText = false; _tillMove = 0; - Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0); initDrawStructs(); } @@ -244,6 +243,7 @@ void Interface::setMainButtons() { * be animated. */ void Interface::perform() { + Combat &combat = *_vm->_combat; EventsManager &events = *_vm->_events; Map &map = *_vm->_map; Party &party = *_vm->_party; @@ -314,7 +314,7 @@ void Interface::perform() { case Common::KEYCODE_w: // Wait one turn chargeStep(); - moveMonsters(); + combat.moveMonsters(); _upDoorText = false; _flipDefaultGround = !_flipDefaultGround; _flipGround = !_flipGround; @@ -456,7 +456,7 @@ void Interface::perform() { if (_buttonValue < (int)party._activeParty.size()) { CharacterInfo::show(_vm, _buttonValue); if (party._stepped) - moveMonsters(); + combat.moveMonsters(); } break; @@ -533,7 +533,7 @@ void Interface::chargeStep() { if (_vm->_party->_partyDead) { _vm->_party->changeTime(_vm->_map->_isOutdoors ? 10 : 1); if (!_tillMove) { - moveMonsters(); + _vm->_combat->moveMonsters(); } _tillMove = 3; @@ -1181,9 +1181,9 @@ void Interface::draw3d(bool updateFlag) { if (_flipUIFrame == 0) _flipWater = !_flipWater; if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_COMBAT) && - !_flag1 && _vm->_moveMonsters) { + !combat._monstersAttacking && _vm->_moveMonsters) { if (--_tillMove == 0) - moveMonsters(); + combat.moveMonsters(); } // Draw the map @@ -1213,8 +1213,8 @@ void Interface::draw3d(bool updateFlag) { if (combat._attackMonsters[0] != -1 || combat._attackMonsters[1] != -1 || combat._attackMonsters[2] != -1) { - if ((_vm->_mode == MODE_1 || _vm->_mode == MODE_SLEEPING) && !_flag1 - && !_charsShooting && _vm->_moveMonsters) { + if ((_vm->_mode == MODE_1 || _vm->_mode == MODE_SLEEPING) && + !combat._monstersAttacking && !_charsShooting && _vm->_moveMonsters) { combat.doCombat(); if (scripts._eventSkipped) scripts.checkEvents(); @@ -1795,8 +1795,4 @@ void Interface::assembleBorder() { screen._windows[12].frame(); } -void Interface::moveMonsters() { - // TODO -} - } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index fa5f1aaec1..297b98465e 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -69,7 +69,6 @@ private: SpriteResource _fecpSprites; SpriteResource _blessSprites; DrawStruct _mainList[16]; - int _combatCharIds[8]; bool _buttonsLoaded; int _steppingFX; @@ -140,8 +139,6 @@ public: void draw3d(bool updateFlag); void assembleBorder(); - - void moveMonsters(); }; } // End of namespace Xeen diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index a3241a133f..d6d15d691f 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -30,8 +30,8 @@ namespace Xeen { static bool debugFlag = false; OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]), - _groundSprite(_data[2]), _combatImgs1(&_data[124]), _combatImgs2(&_data[95]), - _combatImgs3(&_data[76]), _combatImgs4(&_data[53]), _groundTiles(&_data[3]) { + _groundSprite(_data[2]), _attackImgs1(&_data[124]), _attackImgs2(&_data[95]), + _attackImgs3(&_data[76]), _attackImgs4(&_data[53]), _groundTiles(&_data[3]) { _data[0] = DrawStruct(0, 8, 8); _data[1] = DrawStruct(1, 8, 25); _data[2] = DrawStruct(0, 8, 67); @@ -190,8 +190,8 @@ IndoorDrawList::IndoorDrawList() : _objects3(_data[127]), _objects4(_data[97]), _objects5(_data[98]), _objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]), _objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]), - _combatImgs1(&_data[162]), _combatImgs2(&_data[135]), - _combatImgs3(&_data[111]), _combatImgs4(&_data[79]) { + _attackImgs1(&_data[162]), _attackImgs2(&_data[135]), + _attackImgs3(&_data[111]), _attackImgs4(&_data[79]) { // Setup draw structure positions _data[0] = DrawStruct(0, 8, 8); _data[1] = DrawStruct(1, 8, 25); @@ -375,13 +375,12 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) { _flipGround = false; _flipSky = false; _flipDefaultGround = false; - _isShooting = false; + _isAttacking = false; _charsShooting = false; _objNumber = 0; _combatFloatCounter = 0; _thinWall = false; _isAnimReset = false; - _flag1 = false; _overallFrame = 0; _openDoor = false; } @@ -430,27 +429,27 @@ void InterfaceMap::drawMap() { for (int idx = 0; idx < 44; ++idx) _outdoorList[OUTDOOR_DRAWSTRCT_INDEXES[idx]]._frame = -1; - if (_flag1) { + if (combat._monstersAttacking) { for (int idx = 0; idx < 8; ++idx) { - if (_outdoorList._combatImgs4[idx]._sprites) - _outdoorList._combatImgs4[idx]._frame = 0; - else if (_outdoorList._combatImgs3[idx]._sprites) - _outdoorList._combatImgs3[idx]._frame = 1; - else if (_outdoorList._combatImgs2[idx]._sprites) - _outdoorList._combatImgs2[idx]._frame = 2; - else if (_outdoorList._combatImgs1[idx]._sprites) - _outdoorList._combatImgs1[idx]._frame = 0; + if (_outdoorList._attackImgs4[idx]._sprites) + _outdoorList._attackImgs4[idx]._frame = 0; + else if (_outdoorList._attackImgs3[idx]._sprites) + _outdoorList._attackImgs3[idx]._frame = 1; + else if (_outdoorList._attackImgs2[idx]._sprites) + _outdoorList._attackImgs2[idx]._frame = 2; + else if (_outdoorList._attackImgs1[idx]._sprites) + _outdoorList._attackImgs1[idx]._frame = 0; } } else if (_charsShooting) { for (int idx = 0; idx < 8; ++idx) { - if (_outdoorList._combatImgs1[idx]._sprites) - _outdoorList._combatImgs1[idx]._frame = 0; - else if (_outdoorList._combatImgs2[idx]._sprites) - _outdoorList._combatImgs2[idx]._frame = 1; - else if (_outdoorList._combatImgs3[idx]._sprites) - _outdoorList._combatImgs3[idx]._frame = 2; - else if (_outdoorList._combatImgs4[idx]._sprites) - _outdoorList._combatImgs1[idx]._frame = 0; + if (_outdoorList._attackImgs1[idx]._sprites) + _outdoorList._attackImgs1[idx]._frame = 0; + else if (_outdoorList._attackImgs2[idx]._sprites) + _outdoorList._attackImgs2[idx]._frame = 1; + else if (_outdoorList._attackImgs3[idx]._sprites) + _outdoorList._attackImgs3[idx]._frame = 2; + else if (_outdoorList._attackImgs4[idx]._sprites) + _outdoorList._attackImgs1[idx]._frame = 0; } } @@ -557,7 +556,7 @@ void InterfaceMap::drawMap() { for (int idx = 3; idx < _indoorList.size(); ++idx) _indoorList[idx]._frame = -1; - if (_flag1) { + if (combat._monstersAttacking) { for (int idx = 0; idx < 96; ++idx) { if (_indoorList[79 + idx]._sprites != nullptr) { _indoorList[79 + idx]._frame = 0; @@ -762,12 +761,12 @@ void InterfaceMap::animate3d() { } } - DrawStruct *combatImgs1 = map._isOutdoors ? _outdoorList._combatImgs1 : _indoorList._combatImgs1; - DrawStruct *combatImgs2 = map._isOutdoors ? _outdoorList._combatImgs2 : _indoorList._combatImgs2; - DrawStruct *combatImgs3 = map._isOutdoors ? _outdoorList._combatImgs3 : _indoorList._combatImgs3; - DrawStruct *combatImgs4 = map._isOutdoors ? _outdoorList._combatImgs4 : _indoorList._combatImgs4; + DrawStruct *combatImgs1 = map._isOutdoors ? _outdoorList._attackImgs1 : _indoorList._attackImgs1; + DrawStruct *combatImgs2 = map._isOutdoors ? _outdoorList._attackImgs2 : _indoorList._attackImgs2; + DrawStruct *combatImgs3 = map._isOutdoors ? _outdoorList._attackImgs3 : _indoorList._attackImgs3; + DrawStruct *combatImgs4 = map._isOutdoors ? _outdoorList._attackImgs4 : _indoorList._attackImgs4; - if (_flag1) { + if (combat._monstersAttacking) { for (int idx = 0; idx < 8; ++idx) { if (combatImgs1[idx]._sprites) { combatImgs1[idx]._sprites = nullptr; @@ -4326,13 +4325,13 @@ void InterfaceMap::drawIndoors() { _vm->_screen->_windows[3].drawList(&_indoorList[0], _indoorList.size()); // Check for any character shooting - _isShooting = false; + _isAttacking = false; for (uint idx = 0; idx < _vm->_party->_activeParty.size(); ++idx) { if (_vm->_combat->_shooting[idx]) - _isShooting = true; + _isAttacking = true; } - _charsShooting = _isShooting; + _charsShooting = _isAttacking; } /** @@ -4404,13 +4403,13 @@ void InterfaceMap::drawOutdoors() { screen._windows[3].drawList(&_outdoorList[0], _outdoorList.size()); // Check for any character shooting - _isShooting = false; + _isAttacking = false; for (uint idx = 0; idx < _vm->_party->_activeParty.size(); ++idx) { if (_vm->_combat->_shooting[idx]) - _isShooting = true; + _isAttacking = true; } - _charsShooting = _isShooting; + _charsShooting = _isAttacking; } } // End of namespace Xeen diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index 1ff982972f..a37bf349ec 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -37,10 +37,10 @@ public: DrawStruct &_sky1, &_sky2; DrawStruct &_groundSprite; DrawStruct * const _groundTiles; - DrawStruct * const _combatImgs1; - DrawStruct * const _combatImgs2; - DrawStruct * const _combatImgs3; - DrawStruct * const _combatImgs4; + DrawStruct * const _attackImgs1; + DrawStruct * const _attackImgs2; + DrawStruct * const _attackImgs3; + DrawStruct * const _attackImgs4; public: OutdoorDrawList(); @@ -73,10 +73,10 @@ public: DrawStruct &_objects0, &_objects1, &_objects2, &_objects3; DrawStruct &_objects4, &_objects5, &_objects6, &_objects7; DrawStruct &_objects8, &_objects9, &_objects10, &_objects11; - DrawStruct * const _combatImgs1; - DrawStruct * const _combatImgs2; - DrawStruct * const _combatImgs3; - DrawStruct * const _combatImgs4; + DrawStruct * const _attackImgs1; + DrawStruct * const _attackImgs2; + DrawStruct * const _attackImgs3; + DrawStruct * const _attackImgs4; public: IndoorDrawList(); @@ -104,10 +104,8 @@ protected: bool _flipGround; bool _flipSky; bool _flipDefaultGround; - bool _isShooting; bool _thinWall; bool _isAnimReset; - bool _flag1; void setMazeBits(); @@ -122,6 +120,7 @@ public: int _overallFrame; bool _charsShooting; bool _openDoor; + bool _isAttacking; public: InterfaceMap(XeenEngine *vm); -- cgit v1.2.3 From e7ffed76b43471052597bae43afe51c168ded01b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 16 Feb 2015 11:42:29 -0500 Subject: XEEN: Implemented giveCharDamage --- engines/xeen/combat.cpp | 134 ++++++++++++++++++++++++++++++++++++++++++++- engines/xeen/combat.h | 2 +- engines/xeen/interface.cpp | 2 +- 3 files changed, 134 insertions(+), 4 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 3797c18139..9848e8037c 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -104,8 +104,132 @@ void Combat::doCombat() { error("TODO: doCombat"); } -void Combat::giveCharDamage(int damage, int v2, int v3) { - error("TODO: giveCharDamage"); +void Combat::giveCharDamage(int damage, DamageType attackType, int charIndex) { + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + Scripts &scripts = *_vm->_scripts; + SoundManager &sound = *_vm->_sound; + int charIndex1 = charIndex + 1; + int selectedIndex1 = 0; + int selectedIndex2 = 0; + bool breakFlag = false; + + screen.closeWindows(); + + int idx = (int)party._activeParty.size(); + if (!scripts._v2) { + for (idx = 0; idx < (int)party._activeParty.size(); ++idx) { + Character &c = party._activeParty[idx]; + Condition condition = c.worstCondition(); + + if (!(condition >= UNCONSCIOUS && condition <= ERADICATED)) { + if (!selectedIndex1) { + selectedIndex1 = idx + 1; + } else { + selectedIndex2 = idx + 1; + break; + } + } + } + } + if (idx == (int)party._activeParty.size()) { + selectedIndex1 = scripts._v2 ? charIndex : 0; + goto loop; + } + + for (;;) { + // The if below is to get around errors due to the + // goto I was forced to use when reimplementing this method + if (true) { + Character &c = party._activeParty[selectedIndex1]; + c._conditions[ASLEEP] = 0; // Force character to be awake + + int frame = 0, fx = 0; + switch (attackType) { + case DT_PHYSICAL: + fx = 29; + break; + case DT_MAGICAL: + frame = 6; + fx = 27; + break; + case DT_FIRE: + damage -= party._fireResistence; + frame = 1; + fx = 22; + break; + case DT_ELECTRICAL: + damage -= party._electricityResistence; + frame = 2; + fx = 23; + break; + case DT_COLD: + damage -= party._coldResistence; + frame = 3; + fx = 24; + break; + case DT_POISON: + damage -= party._poisonResistence; + frame = 4; + fx = 26; + break; + case DT_ENERGY: + frame = 5; + fx = 25; + break; + case DT_SLEEP: + fx = 38; + break; + default: + break; + } + + // All attack types other than physical allow for saving + // throws to reduce the damage + if (attackType != DT_PHYSICAL) { + while (c.charSavingThrow(attackType) && damage > 0) + damage /= 2; + } + + // Draw the attack effect on the character sprite + sound.playFX(fx); + _powSprites.draw(screen, frame, + Common::Point(CHAR_FACES_X[selectedIndex1], 150)); + screen._windows[33].update(); + + // Reduce damage if power shield active, and set it zero + // if the damage amount has become negative.. you wouldn't + // want attacks healing the characters + if (party._powerShield) + damage -= party._powerShield; + if (damage < 0) + damage = 0; + + // TODO: This seems weird.. maybe I've got attack types wrong.. + // why should attack type 7 (DT_SLEEP) set the dead condition? + if (attackType == DT_SLEEP) { + damage = c._currentHp; + c._conditions[DEAD] = 1; + } + + // Subtract the hit points from the character + c.subtractHitPoints(damage); + } + + if (selectedIndex2) { + ++selectedIndex1; +loop: + if ((scripts._v2 ? charIndex1 : (int)party._activeParty.size()) > selectedIndex1) + break; + } + + // Break check and if not, move to other index + if (!selectedIndex2 || breakFlag) + break; + + selectedIndex1 = selectedIndex2 - 1; + breakFlag = true; + } } void Combat::moveMonsters() { @@ -445,6 +569,12 @@ void Combat::attackMonster(int monsterId) { } bool Combat::stopAttack(const Common::Point &diffPt) { + Map &map = *_vm->_map; + + if (map._isOutdoors) { + + } + // TODO return false; } diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 977d580047..d6ec2333e8 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -95,7 +95,7 @@ public: void doCombat(); - void giveCharDamage(int damage, int v2, int v3); + void giveCharDamage(int damage, DamageType attackType, int charIndex); void moveMonsters(); }; diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index db0bd815aa..c8324a652a 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -839,7 +839,7 @@ void Interface::startFalling(bool flag) { draw3d(true); int tempVal = scripts._v2; scripts._v2 = 0; - combat.giveCharDamage(party._fallDamage, 0, 0); + combat.giveCharDamage(party._fallDamage, DT_PHYSICAL, 0); scripts._v2 = tempVal; _flipGround ^= 1; -- cgit v1.2.3 From 30d94950beb02188644dcfd71f3c3a067d0a0c5a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 16 Feb 2015 14:35:23 -0500 Subject: XEEN: Starting of combat UI, moved _combatParty into Combat class --- engines/xeen/combat.cpp | 12 ++++------ engines/xeen/combat.h | 7 ++++-- engines/xeen/dialogs_char_info.cpp | 11 +++++---- engines/xeen/dialogs_items.cpp | 5 ++-- engines/xeen/dialogs_quick_ref.cpp | 4 ++-- engines/xeen/interface.cpp | 47 ++++++++++++++++++++++++++++++++++---- engines/xeen/interface.h | 4 +++- engines/xeen/party.cpp | 6 ++--- engines/xeen/party.h | 2 -- 9 files changed, 68 insertions(+), 30 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 9848e8037c..d66081754c 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -22,6 +22,7 @@ #include "common/algorithm.h" #include "common/rect.h" +#include "xeen/character.h" #include "xeen/combat.h" #include "xeen/interface.h" #include "xeen/xeen.h" @@ -94,16 +95,13 @@ Combat::Combat(XeenEngine *vm): _vm(vm) { _whosTurn = -1; _itemFlag = false; _monstersAttacking = false; + _combatMode = 0; } void Combat::clear() { Common::fill(&_attackMonsters[0], &_attackMonsters[26], -1); } -void Combat::doCombat() { - error("TODO: doCombat"); -} - void Combat::giveCharDamage(int damage, DamageType attackType, int charIndex) { Party &party = *_vm->_party; Screen &screen = *_vm->_screen; @@ -414,9 +412,9 @@ void Combat::monstersAttack() { if (_vm->_mode != MODE_COMBAT) { // Combat wasn't previously active, but it is now. Set up // the combat party from the currently active party - party._combatParty.clear(); + _combatParty.clear(); for (uint idx = 0; idx < party._activeParty.size(); ++idx) - party._combatParty.push_back(&party._activeParty[idx]); + _combatParty.push_back(&party._activeParty[idx]); } for (int idx = 0; idx < 36; ++idx) { @@ -523,8 +521,6 @@ void Combat::endAttack() { OutdoorDrawList &outdoorList = intf._outdoorList; for (uint idx = 0; idx < party._activeParty.size(); ++idx) { - Character &c = party._activeParty[idx]; - if (map._isOutdoors) { outdoorList._attackImgs1[idx]._scale = 0; outdoorList._attackImgs2[idx]._scale = 0; diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index d6ec2333e8..6b306b4991 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -50,11 +50,15 @@ enum SpecialAttack { }; class XeenEngine; +class Character; class Combat { private: XeenEngine *_vm; public: + Common::Array<Character *> _combatParty; + Common::Array<int> _charsBlocked; + Common::Array<int> _charsGone; SpriteResource _powSprites; int _attackMonsters[26]; int _charsArray1[12]; @@ -71,6 +75,7 @@ public: bool _rangeAttacking[MAX_NUM_MONSTERS]; int _gmonHit[36]; bool _monstersAttacking; + int _combatMode; void monstersAttack(); @@ -93,8 +98,6 @@ public: void clear(); - void doCombat(); - void giveCharDamage(int damage, DamageType attackType, int charIndex); void moveMonsters(); diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp index df4b699a72..c00916cd6f 100644 --- a/engines/xeen/dialogs_char_info.cpp +++ b/engines/xeen/dialogs_char_info.cpp @@ -36,18 +36,19 @@ void CharacterInfo::show(XeenEngine *vm, int charIndex) { } void CharacterInfo::execute(int charIndex) { - Screen &screen = *_vm->_screen; + Combat &combat = *_vm->_combat; EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; Party &party = *_vm->_party; - + Screen &screen = *_vm->_screen; + bool redrawFlag = true; Mode oldMode = _vm->_mode; _vm->_mode = MODE_CHARACTER_INFO; loadDrawStructs(); addButtons(); - Character *c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : party._combatParty[charIndex]; + Character *c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : combat._combatParty[charIndex]; intf.highlightChar(charIndex); Window &w = screen._windows[24]; w.open(); @@ -86,9 +87,9 @@ void CharacterInfo::execute(int charIndex) { case Common::KEYCODE_F5: case Common::KEYCODE_F6: _buttonValue -= Common::KEYCODE_F1; - if (_buttonValue < (int)(oldMode == MODE_COMBAT ? party._combatParty.size() : party._activeParty.size())) { + if (_buttonValue < (int)(oldMode == MODE_COMBAT ? combat._combatParty.size() : party._activeParty.size())) { charIndex = _buttonValue; - c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : party._combatParty[charIndex]; + c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : combat._combatParty[charIndex]; } else { _vm->_mode = MODE_CHARACTER_INFO; } diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index 29ec4c684b..ec82afbbd2 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -37,6 +37,7 @@ Character *ItemsDialog::show(XeenEngine *vm, Character *c, ItemsMode mode) { } Character *ItemsDialog::execute(Character *c, ItemsMode mode) { + Combat &combat = *_vm->_combat; EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; Party &party = *_vm->_party; @@ -337,11 +338,11 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { _buttonValue -= Common::KEYCODE_F1; if (_buttonValue < (int)(_vm->_mode == MODE_COMBAT ? - party._combatParty.size() : party._activeParty.size())) { + combat._combatParty.size() : party._activeParty.size())) { // Character number is valid redrawFlag = REDRAW_TEXT; Character *newChar = _vm->_mode == MODE_COMBAT ? - party._combatParty[_buttonValue] : &party._activeParty[_buttonValue]; + combat._combatParty[_buttonValue] : &party._activeParty[_buttonValue]; if (mode == ITEMMODE_BLACKSMITH) { _oldCharacter = newChar; diff --git a/engines/xeen/dialogs_quick_ref.cpp b/engines/xeen/dialogs_quick_ref.cpp index f4066a0de5..e9ffbd482c 100644 --- a/engines/xeen/dialogs_quick_ref.cpp +++ b/engines/xeen/dialogs_quick_ref.cpp @@ -41,9 +41,9 @@ void QuickReferenceDialog::execute() { events.setCursor(0); - for (uint idx = 0; idx < (combat._globalCombat == 2 ? party._combatParty.size() : + for (uint idx = 0; idx < (combat._globalCombat == 2 ? combat._combatParty.size() : party._activeParty.size()); ++idx) { - Character &c = combat._globalCombat == 2 ? *party._combatParty[idx] : + Character &c = combat._globalCombat == 2 ? *combat._combatParty[idx] : party._activeParty[idx]; Condition condition = c.worstCondition(); lines[idx] = Common::String::format(QUICK_REF_LINE, diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index c8324a652a..479795db4b 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -43,6 +43,7 @@ PartyDrawer::PartyDrawer(XeenEngine *vm): _vm(vm) { } void PartyDrawer::drawParty(bool updateFlag) { + Combat &combat = *_vm->_combat; Party &party = *_vm->_party; Resources &res = *_vm->_resources; Screen &screen = *_vm->_screen; @@ -50,9 +51,9 @@ void PartyDrawer::drawParty(bool updateFlag) { _restoreSprites.draw(screen, 0, Common::Point(8, 149)); // Handle drawing the party faces - uint partyCount = inCombat ? party._combatParty.size() : party._activeParty.size(); + uint partyCount = inCombat ? combat._combatParty.size() : party._activeParty.size(); for (uint idx = 0; idx < partyCount; ++idx) { - Character &ps = inCombat ? *party._combatParty[idx] : party._activeParty[idx]; + Character &ps = inCombat ? *combat._combatParty[idx] : party._activeParty[idx]; Condition charCondition = ps.worstCondition(); int charFrame = FACE_CONDITION_FRAMES[charCondition]; @@ -64,7 +65,7 @@ void PartyDrawer::drawParty(bool updateFlag) { } for (uint idx = 0; idx < partyCount; ++idx) { - Character &ps = inCombat ? *party._combatParty[idx] : party._activeParty[idx]; + Character &ps = inCombat ? *combat._combatParty[idx] : party._activeParty[idx]; // Draw the Hp bar int maxHp = ps.getMaxHP(); @@ -212,7 +213,7 @@ void Interface::mainIconsPrint() { screen._windows[34].update(); } -void Interface::setMainButtons() { +void Interface::setMainButtons(bool combatMode) { clearButtons(); addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_s, &_iconSprites); @@ -236,6 +237,18 @@ void Interface::setMainButtons() { addButton(Common::Rect(239, 37, 312, 47), Common::KEYCODE_2, &_iconSprites, false); addButton(Common::Rect(239, 47, 312, 57), Common::KEYCODE_3, &_iconSprites, false); addPartyButtons(_vm); + + if (combatMode) { + _buttons[0]._value = Common::KEYCODE_f; + _buttons[1]._value = Common::KEYCODE_c; + _buttons[2]._value = Common::KEYCODE_a; + _buttons[3]._value = Common::KEYCODE_u; + _buttons[4]._value = Common::KEYCODE_r; + _buttons[5]._value = Common::KEYCODE_b; + _buttons[6]._value = Common::KEYCODE_o; + _buttons[7]._value = Common::KEYCODE_i; + _buttons[16]._value = 0; + } } /** @@ -1215,7 +1228,7 @@ void Interface::draw3d(bool updateFlag) { || combat._attackMonsters[2] != -1) { if ((_vm->_mode == MODE_1 || _vm->_mode == MODE_SLEEPING) && !combat._monstersAttacking && !_charsShooting && _vm->_moveMonsters) { - combat.doCombat(); + doCombat(); if (scripts._eventSkipped) scripts.checkEvents(); } @@ -1795,4 +1808,28 @@ void Interface::assembleBorder() { screen._windows[12].frame(); } +void Interface::doCombat() { + Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; + Screen &screen = *_vm->_screen; + bool isDarkCc = _vm->_files->_isDarkCc; + bool upDoorText = _upDoorText; + + _upDoorText = false; + combat._combatMode = 2; + _vm->_mode = MODE_COMBAT; + + _iconSprites.load("combat.icn"); + for (int idx = 1; idx < 16; ++idx) + _mainList[idx]._sprites = nullptr; + + // Set the combat buttons + setMainButtons(true); + mainIconsPrint(); + + + + error("TODO"); +} + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 297b98465e..40926ac6ea 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -84,7 +84,7 @@ private: void setupBackground(); - void setMainButtons(); + void setMainButtons(bool combatMode = false); void chargeStep(); @@ -139,6 +139,8 @@ public: void draw3d(bool updateFlag); void assembleBorder(); + + void doCombat(); }; } // End of namespace Xeen diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 2eb4cc2027..3913ad6a0d 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -105,7 +105,6 @@ Party::Party(XeenEngine *vm) { for (int i = 0; i < TOTAL_CHARACTERS; ++i) Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false); - _combatPartyCount = 0; _partyDead = false; _newDay = false; _isNight = false; @@ -531,10 +530,11 @@ void Party::notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wa } void Party::checkPartyDead() { + Combat &combat = *_vm->_combat; bool inCombat = _vm->_mode == MODE_COMBAT; - for (uint charIdx = 0; charIdx < (inCombat ? _combatParty.size() : _activeParty.size()); ++charIdx) { - Character &c = inCombat ? *_combatParty[charIdx] : _activeParty[charIdx]; + for (uint charIdx = 0; charIdx < (inCombat ? combat._combatParty.size() : _activeParty.size()); ++charIdx) { + Character &c = inCombat ? *combat._combatParty[charIdx] : _activeParty[charIdx]; Condition cond = c.worstCondition(); if (cond <= CONFUSED || cond == NO_CONDITION) { _dead = false; diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 4f32cca243..035b344c9b 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -115,8 +115,6 @@ public: // Other party related runtime data Roster _roster; Common::Array<Character> _activeParty; - Common::Array<Character *> _combatParty; - int _combatPartyCount; bool _partyDead; bool _newDay; bool _isNight; -- cgit v1.2.3 From c045adae76e414a8e6b57e48a651ea6c29ed280a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 16 Feb 2015 19:58:53 -0500 Subject: XEEN: Implementing more combat logic --- engines/xeen/character.cpp | 25 +++ engines/xeen/character.h | 4 + engines/xeen/combat.cpp | 154 +++++++++++++- engines/xeen/combat.h | 29 ++- engines/xeen/dialogs_control_panel.cpp | 42 ++++ engines/xeen/dialogs_control_panel.h | 43 ++++ engines/xeen/dialogs_fight_options.cpp | 39 ++++ engines/xeen/dialogs_fight_options.h | 43 ++++ engines/xeen/interface.cpp | 358 ++++++++++++++++++++++++++++++++- engines/xeen/interface.h | 4 + engines/xeen/map.cpp | 9 +- engines/xeen/map.h | 2 +- engines/xeen/module.mk | 2 + engines/xeen/party.cpp | 7 + engines/xeen/party.h | 2 + engines/xeen/resources.cpp | 2 + engines/xeen/resources.h | 2 + engines/xeen/scripts.cpp | 2 +- 18 files changed, 754 insertions(+), 15 deletions(-) create mode 100644 engines/xeen/dialogs_control_panel.cpp create mode 100644 engines/xeen/dialogs_control_panel.h create mode 100644 engines/xeen/dialogs_fight_options.cpp create mode 100644 engines/xeen/dialogs_fight_options.h (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index ac25b32c55..afe385448a 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -818,6 +818,9 @@ void Character::synchronize(Common::Serializer &s) { s.syncAsByte(_currentCombatSpell); } +/** + * Returns the worst condition the character is suffering from + */ Condition Character::worstCondition() const { for (int cond = ERADICATED; cond >= CURSED; --cond) { if (_conditions[cond]) @@ -827,6 +830,28 @@ Condition Character::worstCondition() const { return NO_CONDITION; } +/** + * Returns whether the given character has a disabling condition, but still alive + */ +bool Character::isDisabled() const { + Condition condition = worstCondition(); + + return condition == ASLEEP || condition == PARALYZED || condition == UNCONSCIOUS + || condition == STONED || condition == ERADICATED; +} + +/** +* Returns whether the given character has a disabling condition, or is dead +*/ +bool Character::isDisabledOrDead() const { + Condition condition = worstCondition(); + + return condition == ASLEEP || (condition >= PARALYZED && condition <= ERADICATED); +} + +/** + * Get the character's age + */ int Character::getAge(bool ignoreTemp) const { int year = MIN(Party::_vm->_party->_year - _birthYear, (uint)254); diff --git a/engines/xeen/character.h b/engines/xeen/character.h index 9e8687dbd7..be38ba5da1 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -270,6 +270,10 @@ public: Condition worstCondition() const; + bool isDisabled() const; + + bool isDisabledOrDead() const; + int getAge(bool ignoreTemp = false) const; int getMaxHP() const; diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index d66081754c..c8f5824db9 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -96,6 +96,10 @@ Combat::Combat(XeenEngine *vm): _vm(vm) { _itemFlag = false; _monstersAttacking = false; _combatMode = 0; + _monsterIndex = 0; + _partyRan = false; + _monster2Attack = -1; + _whosSpeed = 0; } void Combat::clear() { @@ -412,9 +416,7 @@ void Combat::monstersAttack() { if (_vm->_mode != MODE_COMBAT) { // Combat wasn't previously active, but it is now. Set up // the combat party from the currently active party - _combatParty.clear(); - for (uint idx = 0; idx < party._activeParty.size(); ++idx) - _combatParty.push_back(&party._activeParty[idx]); + setupCombatParty(); } for (int idx = 0; idx < 36; ++idx) { @@ -575,4 +577,150 @@ bool Combat::stopAttack(const Common::Point &diffPt) { return false; } +/** + * Setup the combat party with a copy of the currently active party + */ +void Combat::setupCombatParty() { + Party &party = *_vm->_party; + + _combatParty.clear(); + for (uint idx = 0; idx < party._activeParty.size(); ++idx) + _combatParty.push_back(&party._activeParty[idx]); +} + +void Combat::setSpeedTable() { + Map &map = *_vm->_map; + Common::Array<int> charSpeeds; + bool flag = _whosSpeed != -1; + int oldSpeed = (_whosSpeed == -1) ? 0 : _speedTable[_whosSpeed]; + + Common::fill(&_speedTable[0], &_speedTable[12], -1); + Common::fill(&charSpeeds[0], &charSpeeds[12], -1); + + // Set up speeds for party membres + int maxSpeed = 0; + for (uint charNum = 0; charNum < _combatParty.size(); ++charNum) { + Character &c = *_combatParty[charNum]; + charSpeeds.push_back(c.getStat(SPEED)); + + maxSpeed = MAX(charSpeeds[charNum], maxSpeed); + } + + // Add in speeds of attacking monsters + for (int monsterNum = 0; monsterNum < 3; ++monsterNum) { + if (_attackMonsters[monsterNum] != -1) { + MazeMonster &monster = map._mobData._monsters[_attackMonsters[monsterNum]]; + MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + charSpeeds.push_back(monsterData._speed); + + maxSpeed = MAX(maxSpeed, monsterData._speed); + } else { + charSpeeds.push_back(0); + } + } + + _speedTable.clear(); + for (; maxSpeed >= 0; --maxSpeed) { + for (uint idx = 0; idx < charSpeeds.size(); ++idx) { + if (charSpeeds[idx] == maxSpeed) + _speedTable.push_back(idx); + } + } + + if (flag) { + if (_speedTable[_whosSpeed] != oldSpeed) { + for (uint idx = 0; idx < charSpeeds.size(); ++idx) { + if (oldSpeed == _speedTable[idx]) { + _whosSpeed = idx; + break; + } + } + } + } +} + +/** + * Returns true if all participants in the combat are disabled + */ +bool Combat::allHaveGone() const { + for (uint idx = 0; idx < _charsGone.size(); ++idx) { + if (!_charsGone[idx]) { + if (idx >= _combatParty.size()) { + return false; + } else { + Condition condition = _combatParty[idx]->worstCondition(); + if (condition < PARALYZED || condition == NO_CONDITION) + return false; + } + } + } + + return true; +} + +bool Combat::charsCantAct() const { + for (uint idx = 0; idx < _combatParty.size(); ++idx) { + Condition condition = _combatParty[idx]->worstCondition(); + + if (!(condition == ASLEEP || (condition >= PARALYZED && condition != NO_CONDITION))) + return false; + } + + return true; +} + +Common::String Combat::getMonsterDescriptions() { + Map &map = *_vm->_map; + Common::String lines[3]; + + // Get names of monsters attacking, if any + for (int idx = 0; idx < 3; ++idx) { + if (_attackMonsters[idx] != -1) { + MazeMonster &monster = map._mobData._monsters[_attackMonsters[idx]]; + MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + + Common::String format = "\n\v020\f%2u%s\fd"; + format.setChar('2' + idx, 3); + lines[idx] = Common::String::format(format.c_str(), monsterData._name.c_str()); + } + } + + if (_monsterIndex == 2 && _attackMonsters[2] != -1) { + _monster2Attack = _attackMonsters[2]; + } if (_monsterIndex == 1 && _attackMonsters[1] != -1) { + _monster2Attack = _attackMonsters[1]; + } else { + _monster2Attack = _attackMonsters[0]; + _monsterIndex = 0; + } + + return Common::String::format(COMBAT_DETAILS, lines[0].c_str(), + lines[1].c_str(), lines[2].c_str()); +} + +void Combat::attack(Character &c, int v2) { + error("TODO"); +} + +void Combat::block() { + _charsBlocked[_whosTurn] = true; +} + +bool Combat::castSpell(bool flag) { + error("TODO: castSpell"); +} + +void Combat::quickFight() { + error("TODO: quickFight"); +} + +void Combat::giveTreasure() { + error("TODO: giveTreasure"); +} + +void Combat::run() { + error("TODO: run"); +} + + } // End of namespace Xeen diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 6b306b4991..dee15edf6c 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -57,15 +57,17 @@ private: XeenEngine *_vm; public: Common::Array<Character *> _combatParty; - Common::Array<int> _charsBlocked; + Common::Array<bool> _charsBlocked; Common::Array<int> _charsGone; SpriteResource _powSprites; int _attackMonsters[26]; + int _monster2Attack; int _charsArray1[12]; bool _monPow[12]; int _monsterScale[12]; int _elemPow[12]; int _elemScale[12]; + Common::Array<int> _speedTable; int _shooting[8]; int _globalCombat; int _whosTurn; @@ -76,6 +78,9 @@ public: int _gmonHit[36]; bool _monstersAttacking; int _combatMode; + int _monsterIndex; + bool _partyRan; + int _whosSpeed; void monstersAttack(); @@ -101,6 +106,28 @@ public: void giveCharDamage(int damage, DamageType attackType, int charIndex); void moveMonsters(); + + void setupCombatParty(); + + void setSpeedTable(); + + bool allHaveGone() const; + + bool charsCantAct() const; + + Common::String getMonsterDescriptions(); + + void attack(Character &c, int v2); + + void block(); + + bool castSpell(bool flag); + + void quickFight(); + + void giveTreasure(); + + void run(); }; } // End of namespace Xeen diff --git a/engines/xeen/dialogs_control_panel.cpp b/engines/xeen/dialogs_control_panel.cpp new file mode 100644 index 0000000000..7e8f89cc39 --- /dev/null +++ b/engines/xeen/dialogs_control_panel.cpp @@ -0,0 +1,42 @@ +/* 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 "xeen/dialogs_control_panel.h" +#include "xeen/party.h" +#include "xeen/resources.h" +#include "xeen/xeen.h" + +namespace Xeen { + +int ControlPanel::show(XeenEngine *vm) { + ControlPanel *dlg = new ControlPanel(vm); + int result = dlg->execute(); + delete dlg; + + return result; +} + +int ControlPanel::execute() { + error("TODO: ControlPanel"); +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_control_panel.h b/engines/xeen/dialogs_control_panel.h new file mode 100644 index 0000000000..16c3781789 --- /dev/null +++ b/engines/xeen/dialogs_control_panel.h @@ -0,0 +1,43 @@ +/* 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 XEEN_DIALOGS_CONTROL_PANEL_H +#define XEEN_DIALOGS_CONTROL_PANEL_H + +#include "xeen/dialogs.h" + +namespace Xeen { + +class ControlPanel : public ButtonContainer { +private: + XeenEngine *_vm; + + ControlPanel(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + int execute(); +public: + static int show(XeenEngine *vm); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_CONTROL_PANEL_H */ diff --git a/engines/xeen/dialogs_fight_options.cpp b/engines/xeen/dialogs_fight_options.cpp new file mode 100644 index 0000000000..c84e754dc2 --- /dev/null +++ b/engines/xeen/dialogs_fight_options.cpp @@ -0,0 +1,39 @@ +/* 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 "xeen/dialogs_fight_options.h" +#include "xeen/resources.h" +#include "xeen/xeen.h" + +namespace Xeen { + +void FightOptions::show(XeenEngine *vm) { + FightOptions *dlg = new FightOptions(vm); + dlg->execute(); + delete dlg; +} + +void FightOptions::execute() { + error("TODO: FightOptions"); +} + +} // End of namespace Xeen diff --git a/engines/xeen/dialogs_fight_options.h b/engines/xeen/dialogs_fight_options.h new file mode 100644 index 0000000000..7b058bc6e9 --- /dev/null +++ b/engines/xeen/dialogs_fight_options.h @@ -0,0 +1,43 @@ +/* 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 XEEN_DIALOGS_FIGHT_OPTIONS_H +#define XEEN_DIALOGS_FIGHT_OPTIONS_H + +#include "xeen/dialogs.h" + +namespace Xeen { + +class FightOptions : public ButtonContainer { +private: + XeenEngine *_vm; + + FightOptions(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + void execute(); +public: + static void show(XeenEngine *vm); +}; + +} // End of namespace Xeen + +#endif /* XEEN_DIALOGS_FIGHT_OPTIONS_H */ diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 479795db4b..a8396288ee 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -21,10 +21,13 @@ */ #include "xeen/interface.h" +#include "xeen/dialogs_automap.h" #include "xeen/dialogs_char_info.h" +#include "xeen/dialogs_control_panel.h" #include "xeen/dialogs_error.h" -#include "xeen/dialogs_automap.h" +#include "xeen/dialogs_fight_options.h" #include "xeen/dialogs_info.h" +#include "xeen/dialogs_items.h" #include "xeen/dialogs_query.h" #include "xeen/dialogs_quests.h" #include "xeen/dialogs_quick_ref.h" @@ -121,6 +124,9 @@ void PartyDrawer::unhighlightChar() { } } +void PartyDrawer::resetHighlight() { + _hiliteChar = -1; +} /*------------------------------------------------------------------------*/ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), @@ -320,7 +326,11 @@ void Interface::perform() { case Common::KEYCODE_TAB: // Stop mosters doing any movement _vm->_moveMonsters = false; - warning("TODO: showControlPanel"); + if (ControlPanel::show(_vm) == -1) { + _vm->_quitMode = 2; + } else { + _vm->_moveMonsters = 1; + } break; case Common::KEYCODE_SPACE: @@ -1811,9 +1821,13 @@ void Interface::assembleBorder() { void Interface::doCombat() { Combat &combat = *_vm->_combat; EventsManager &events = *_vm->_events; + Map &map = *_vm->_map; + Party &party = *_vm->_party; Screen &screen = *_vm->_screen; - bool isDarkCc = _vm->_files->_isDarkCc; + Scripts &scripts = *_vm->_scripts; + SoundManager &sound = *_vm->_sound; bool upDoorText = _upDoorText; + bool reloadMap = false; _upDoorText = false; combat._combatMode = 2; @@ -1827,9 +1841,345 @@ void Interface::doCombat() { setMainButtons(true); mainIconsPrint(); + combat._combatParty.clear(); + combat._charsGone.clear(); + combat._charsBlocked.clear(); + combat._charsArray1[0] = 0; + combat._charsArray1[1] = 0; + combat._charsArray1[2] = 0; + combat._monstersAttacking = 0; + combat._partyRan = false; + + // Set up the combat party + combat.setupCombatParty(); + combat.setSpeedTable(); + combat._whosSpeed = -1; + combat._whosTurn = -1; + resetHighlight(); + + nextChar(); + + if (!party._dead) { + combat.setSpeedTable(); + if (_tillMove) { + combat.moveMonsters(); + draw3d(true); + } + + Window &w = screen._windows[2]; + w.open(); + bool breakFlag = false; + + while (!_vm->shouldQuit() && !breakFlag) { + highlightChar(combat._whosTurn); + combat.setSpeedTable(); + + // Write out the description of the monsters being battled + w.writeString(combat.getMonsterDescriptions()); + _iconSprites.draw(screen, 32, Common::Point(233, combat._monsterIndex * 10 + 27), + 0x8010000); + w.update(); + + // Wait for keypress + int index = 0; + do { + events.updateGameCounter(); + draw3d(true); + + if (++index == 5 && combat._attackMonsters[0] != -1) { + MazeMonster &monster = map._mobData._monsters[combat._monster2Attack]; + MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + sound.playFX(monsterData._fx); + } + + do { + events.pollEventsAndWait(); + checkEvents(_vm); + } while (!_vm->shouldQuit() && events.timeElapsed() < 1 && !_buttonValue); + } while (!_vm->shouldQuit() && !_buttonValue); + if (_vm->shouldQuit()) + return; + + switch (_buttonValue) { + case Common::KEYCODE_TAB: + // Show the control panel + if (ControlPanel::show(_vm) == 2) { + reloadMap = true; + breakFlag = true; + } else { + highlightChar(combat._whosTurn); + } + break; + + case Common::KEYCODE_1: + case Common::KEYCODE_2: + case Common::KEYCODE_3: + _buttonValue -= Common::KEYCODE_1; + if (combat._attackMonsters[_buttonValue] != -1) { + combat._monster2Attack = combat._attackMonsters[_buttonValue]; + combat._monsterIndex = _buttonValue; + } + break; + + case Common::KEYCODE_a: + // Attack + combat.attack(*combat._combatParty[combat._whosTurn], 0); + nextChar(); + break; + + case Common::KEYCODE_b: + // Block + combat.block(); + nextChar(); + break; + + case Common::KEYCODE_c: + // Cast Spell + if (combat.castSpell(false)) { + nextChar(); + } else { + highlightChar(combat._combatParty[combat._whosTurn]->_rosterId); + } + break; + + case Common::KEYCODE_f: + // Quick Fight + combat.quickFight(); + nextChar(); + break; + + case Common::KEYCODE_i: + // Info dialog + InfoDialog::show(_vm); + highlightChar(combat._whosTurn); + break; + + case Common::KEYCODE_o: + // Fight Options + FightOptions::show(_vm); + highlightChar(combat._whosTurn); + break; + + case Common::KEYCODE_q: + // Quick Reference dialog + QuickReferenceDialog::show(_vm); + highlightChar(combat._whosTurn); + break; + + case Common::KEYCODE_r: + // Run from combat + combat.run(); + nextChar(); + + if (_vm->_mode == MODE_1) { + warning("TODO: loss of treasure"); + party.moveToRunLocation(); + breakFlag = true; + } + break; + + case Common::KEYCODE_u: { + int whosTurn = combat._whosTurn; + ItemsDialog::show(_vm, combat._combatParty[combat._whosTurn], ITEMMODE_COMBAT); + if (combat._whosTurn == whosTurn) { + highlightChar(combat._whosTurn); + } else { + combat._whosTurn = whosTurn; + nextChar(); + } + break; + } + + case Common::KEYCODE_F1: + case Common::KEYCODE_F2: + case Common::KEYCODE_F3: + case Common::KEYCODE_F4: + case Common::KEYCODE_F5: + case Common::KEYCODE_F6: + // Show character info + _buttonValue -= Common::KEYCODE_F1; + if (_buttonValue < (int)combat._combatParty.size()) { + CharacterInfo::show(_vm, _buttonValue); + } + highlightChar(combat._whosTurn); + break; + + case Common::KEYCODE_LEFT: + case Common::KEYCODE_RIGHT: + // Rotate party direction left or right + if (_buttonValue == Common::KEYCODE_LEFT) { + party._mazeDirection = (party._mazeDirection == DIR_NORTH) ? + DIR_WEST : (Direction)((int)party._mazeDirection - 1); + } else { + party._mazeDirection = (party._mazeDirection == DIR_WEST) ? + DIR_NORTH : (Direction)((int)party._mazeDirection + 1); + } + + _flipSky ^= 1; + if (_tillMove) + combat.moveMonsters(); + party._stepped = true; + break; + } + + // Handling for if the combat turn is complete + if (combat.allHaveGone()) { + Common::fill(&combat._charsGone[0], &combat._charsGone[combat._charsGone.size()], false); + Common::fill(&combat._charsBlocked[0], &combat._charsBlocked[combat._charsBlocked.size()], false); + combat.setSpeedTable(); + combat._whosTurn = -1; + combat._whosSpeed = -1; + nextChar(); + + for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) { + MazeMonster &monster = map._mobData._monsters[idx]; + if (monster._spriteId == 53) { + warning("TODO: Monster 53's HP is altered here?!"); + } + } + + combat.moveMonsters(); + setIndoorsMonsters(); + party.changeTime(1); + } + + if (combat._attackMonsters[0] == -1 && combat._attackMonsters[1] == -1 + && combat._attackMonsters[2] == -1) { + party.changeTime(1); + draw3d(true); + + if (combat._attackMonsters[0] == -1 && combat._attackMonsters[1] == -1 + && combat._attackMonsters[2] == -1) + break; + } + + party.checkPartyDead(); + if (party._dead || _vm->_mode != MODE_COMBAT) + break; + } + + _vm->_mode = MODE_1; + if (combat._partyRan && (combat._attackMonsters[0] != -1 || + combat._attackMonsters[1] != -1 || combat._attackMonsters[2] != -1)) { + party.checkPartyDead(); + if (!party._dead) { + party.moveToRunLocation(); + + for (uint idx = 0; idx < combat._combatParty.size(); ++idx) { + Character &c = *combat._combatParty[idx]; + if (c.isDisabled()) + c._conditions[DEAD] = 1; + } + } + } + + w.close(); + events.clearEvents(); + + _vm->_mode = MODE_COMBAT; + draw3d(true); + combat.giveTreasure(); + _vm->_mode = MODE_1; + party._stepped = true; + unhighlightChar(); + + combat.setupCombatParty(); + drawParty(true); + } + + _iconSprites.load("main.icn"); + for (int idx = 1; idx < 16; ++idx) + _mainList[idx]._sprites = &_iconSprites; + + setMainButtons(); + mainIconsPrint(); + combat._monster2Attack = -1; + + if (upDoorText) { + map.cellFlagLookup(party._mazePosition); + if (map._currentIsEvent) + scripts.checkEvents(); + } + + if (reloadMap) { + sound.playFX(51); + map._loadDarkSide = _vm->getGameID() != GType_WorldOfXeen; + map.load(_vm->getGameID() == GType_WorldOfXeen ? 28 : 29); + party._mazeDirection = _vm->getGameID() == GType_WorldOfXeen ? + DIR_EAST : DIR_SOUTH; + } + combat._combatMode = 1; +} - error("TODO"); +/** + * Select next character or monster to be attacking + */ +void Interface::nextChar() { + Combat &combat = *_vm->_combat; + Party &party = *_vm->_party; + + if (combat.allHaveGone()) + return; + if ((combat._attackMonsters[0] == -1 && combat._attackMonsters[1] == -1 && + combat._attackMonsters[2] == -1) || combat._combatParty.size() == 0) { + _vm->_mode = MODE_1; + return; + } + + for (;;) { + // Check if party is dead + party.checkPartyDead(); + if (party._dead) { + _vm->_mode = MODE_1; + break; + } + + if (combat._whosTurn < (int)combat._combatParty.size()) { + if (!combat.allHaveGone()) + highlightChar(combat._whosTurn); + break; + } else { + combat.attackMonster(0); + if (!party._dead) + party.checkPartyDead(); + + if (party._dead) + break; + } + + // Check the combat participants + bool resetFlag = false; + for (uint idx = 0; idx < combat._speedTable.size(); ++idx) { + // Mark the given character as haven taken their turn + if (combat._whosTurn != -1) { + combat._charsGone[combat._whosTurn] = true; + } + + combat._whosSpeed %= combat._speedTable.size(); + combat._whosTurn = combat._speedTable[combat._whosSpeed]; + + if (combat.allHaveGone()) { + if (combat.charsCantAct()) { + combat.setSpeedTable(); + combat._whosTurn = -1; + combat._whosSpeed = -1; + + combat._charsGone.resize(combat._speedTable.size()); + Common::fill(&combat._charsGone[0], &combat._charsGone[combat._charsGone.size()], 0); + resetFlag = true; + break; + } + return; + } else if (combat._whosTurn >= (int)combat._combatParty.size() || + !combat._combatParty[combat._whosTurn]->isDisabledOrDead()) { + break; + } + } + + if (party._dead) + break; + } } } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 40926ac6ea..80b798047c 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -54,6 +54,8 @@ public: void highlightChar(int charId); void unhighlightChar(); + + void resetHighlight(); }; /** @@ -103,6 +105,8 @@ private: void shake(int time); void drawMiniMap(); + + void nextChar(); public: int _intrIndex1; Common::String _interfaceText; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 1c7cbd8a39..01c050a10a 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -67,7 +67,7 @@ MonsterStruct::MonsterStruct() { _imageNumber = 0; _loopAnimation = 0; _animationEffect = 0; - _field32 = 0; + _fx = 0; } MonsterStruct::MonsterStruct(Common::String name, int experience, int hp, int accuracy, @@ -78,7 +78,7 @@ MonsterStruct::MonsterStruct(Common::String name, int experience, int hp, int ac int poisonResistence, int energyResistence, int magicResistence, int phsyicalResistence, int field29, int gold, int gems, int itemDrop, bool flying, int imageNumber, int loopAnimation, int animationEffect, - int field32, Common::String attackVoc): + int fx, Common::String attackVoc): _name(name), _experience(experience), _hp(hp), _accuracy(accuracy), _speed(speed), _numberOfAttacks(numberOfAttacks), _hatesClass(hatesClass), _strikes(strikes), _dmgPerStrike(dmgPerStrike), _attackType(attackType), @@ -89,10 +89,9 @@ MonsterStruct::MonsterStruct(Common::String name, int experience, int hp, int ac _magicResistence(magicResistence), _phsyicalResistence(phsyicalResistence), _field29(field29), _gold(gold), _gems(gems), _itemDrop(itemDrop), _flying(flying), _imageNumber(imageNumber), _loopAnimation(loopAnimation), - _animationEffect(animationEffect), _field32(field32), _attackVoc(attackVoc) { + _animationEffect(animationEffect), _fx(fx), _attackVoc(attackVoc) { } - void MonsterStruct::synchronize(Common::SeekableReadStream &s) { char name[16]; s.read(name, 16); @@ -127,7 +126,7 @@ void MonsterStruct::synchronize(Common::SeekableReadStream &s) { _imageNumber = s.readByte(); _loopAnimation = s.readByte(); _animationEffect = s.readByte(); - _field32 = s.readByte(); + _fx = s.readByte(); char attackVoc[10]; s.read(attackVoc, 9); diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 806b4084c7..a43cef516e 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -77,7 +77,7 @@ public: int _imageNumber; int _loopAnimation; int _animationEffect; - int _field32; + int _fx; Common::String _attackVoc; public: MonsterStruct(); diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 083abb9a8c..a17311c6af 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -12,9 +12,11 @@ MODULE_OBJS := \ automap.o \ dialogs_automap.o \ dialogs_char_info.o \ + dialogs_control_panel.o \ dialogs_dismiss.o \ dialogs_error.o \ dialogs_exchange.o \ + dialogs_fight_options.o \ dialogs_options.o \ dialogs_info.o \ dialogs_input.o \ diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 3913ad6a0d..993f156204 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -545,4 +545,11 @@ void Party::checkPartyDead() { _dead = true; } +/** + * Move party position to the run destination on the current map + */ +void Party::moveToRunLocation() { + _mazePosition = _vm->_map->mazeData()._runPosition; +} + } // End of namespace Xeen diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 035b344c9b..5d98c55b82 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -150,6 +150,8 @@ public: void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait); void checkPartyDead(); + + void moveToRunLocation(); }; } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 7dca04fd03..c57b6a72cc 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1496,4 +1496,6 @@ const int NEW_CHARACTER_SPELLS[10][4] = { { 20, 1, -1, -1 } }; +const char *const COMBAT_DETAILS = "\r\f00\x03c\v000\t000\x02Combat%s%s%s\x1"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 53c548fbf5..d6902129e8 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -522,6 +522,8 @@ extern const int RACE_ENERGY_RESISTENCES[5]; extern const int RACE_POISON_RESISTENCES[5]; extern const int NEW_CHARACTER_SPELLS[10][4]; +extern const char *const COMBAT_DETAILS; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 086c0d436a..37222a3d76 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -378,7 +378,7 @@ void Scripts::cmdTeleport(Common::Array<byte> ¶ms) { } if (pt.x == 999) { - party._mazePosition = map.mazeData()._runPosition; + party.moveToRunLocation(); } else { party._mazePosition = pt; } -- cgit v1.2.3 From 7b3c10b09c76c4a8cbd5dbfabb0ceeaeccbbce26 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 17 Feb 2015 21:47:01 -0500 Subject: XEEN: Implemented Cast Spell dialog --- engines/xeen/character.cpp | 18 ++++- engines/xeen/character.h | 10 ++- engines/xeen/combat.cpp | 62 +++++++++++++++--- engines/xeen/combat.h | 4 +- engines/xeen/dialogs_error.cpp | 30 +++++++++ engines/xeen/dialogs_error.h | 11 ++++ engines/xeen/dialogs_spells.cpp | 142 ++++++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_spells.h | 15 +++++ engines/xeen/interface.cpp | 31 ++++++--- engines/xeen/resources.cpp | 15 +++++ engines/xeen/resources.h | 5 ++ engines/xeen/spells.cpp | 31 +++++++++ engines/xeen/spells.h | 5 ++ 13 files changed, 356 insertions(+), 23 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index afe385448a..c91b860640 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -707,7 +707,7 @@ void Character::clear() { _lloydMap = 0; _hasSpells = false; _currentSpell = 0; - _quickOption = 0; + _quickOption = QUICK_ATTACK; _lloydSide = 0; Common::fill(&_conditions[0], &_conditions[16], 0); _townUnknown = 0; @@ -1822,4 +1822,20 @@ bool Character::hasSpecialItem() const { return false; } +int Character::getClassCategory() const { + switch (_class) { + case CLASS_ARCHER: + case CLASS_SORCERER: + return 1; + + case CLASS_DRUID: + case CLASS_RANGER: + return 2; + + default: + return 0; + } +} + + } // End of namespace Xeen diff --git a/engines/xeen/character.h b/engines/xeen/character.h index be38ba5da1..bf77bef315 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -85,6 +85,10 @@ enum AttributeCategory { ATTR_ARMOR_CLASS = 8, ATTR_THIEVERY = 9 }; +enum QuickAction { + QUICK_ATTACK = 0, QUICK_SPELL = 1, QUICK_BLOCK = 2, QUICK_RUN = 3 +}; + class XeenEngine; class Character; @@ -235,8 +239,8 @@ public: int _lloydMap; Common::Point _lloydPosition; bool _hasSpells; - int _currentSpell; - int _quickOption; + int8 _currentSpell; + QuickAction _quickOption; InventoryItemsGroup _items; WeaponItems _weapons; ArmorItems _armor; @@ -321,6 +325,8 @@ public: void subtractHitPoints(int amount); bool hasSpecialItem() const; + + int getClassCategory() const; }; } // End of namespace Xeen diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index c8f5824db9..b77ef6e95d 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -100,6 +100,8 @@ Combat::Combat(XeenEngine *vm): _vm(vm) { _partyRan = false; _monster2Attack = -1; _whosSpeed = 0; + _damageType = DT_PHYSICAL; + _oldCharacter = nullptr; } void Combat::clear() { @@ -658,17 +660,21 @@ bool Combat::allHaveGone() const { return true; } +/** + * Returns true if all the characters of the party are disabled + */ bool Combat::charsCantAct() const { for (uint idx = 0; idx < _combatParty.size(); ++idx) { - Condition condition = _combatParty[idx]->worstCondition(); - - if (!(condition == ASLEEP || (condition >= PARALYZED && condition != NO_CONDITION))) + if (!_combatParty[idx]->isDisabledOrDead()) return false; } return true; } +/** + * Return a description of the monsters being faced + */ Common::String Combat::getMonsterDescriptions() { Map &map = *_vm->_map; Common::String lines[3]; @@ -702,25 +708,61 @@ void Combat::attack(Character &c, int v2) { error("TODO"); } +/** + * Flag the currently active character as blocking/defending + */ void Combat::block() { _charsBlocked[_whosTurn] = true; } -bool Combat::castSpell(bool flag) { - error("TODO: castSpell"); -} - +/** + * Perform whatever the current combat character's quick action is + */ void Combat::quickFight() { - error("TODO: quickFight"); + Spells &spells = *_vm->_spells; + Character *c = _combatParty[_whosTurn]; + int spellId; + + switch (c->_quickOption) { + case QUICK_ATTACK: + attack(*c, 0); + break; + case QUICK_SPELL: + if (c->_currentSpell != -1) { + spells.castSpell(SPELLS_ALLOWED[c->getClassCategory()][c->_currentSpell]); + } + break; + case QUICK_BLOCK: + block(); + break; + case QUICK_RUN: + run(); + break; + default: + break; + } } void Combat::giveTreasure() { error("TODO: giveTreasure"); } +/** + * Current selected character is trying to run away + */ void Combat::run() { - error("TODO: run"); -} + Map &map = *_vm->_map; + SoundManager &sound = *_vm->_sound; + if (_vm->getRandomNumber(1, 100) < map.mazeData()._difficulties._chance2Run) { + // Remove the character from the combat party + _combatParty.remove_at(_whosTurn); + setSpeedTable(); + --_whosSpeed; + _whosTurn = -1; + _partyRan = true; + sound.playFX(51); + } +} } // End of namespace Xeen diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index dee15edf6c..5ff6beb16b 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -81,6 +81,8 @@ public: int _monsterIndex; bool _partyRan; int _whosSpeed; + DamageType _damageType; + Character *_oldCharacter; void monstersAttack(); @@ -121,8 +123,6 @@ public: void block(); - bool castSpell(bool flag); - void quickFight(); void giveTreasure(); diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp index db2603ab87..7f649afd86 100644 --- a/engines/xeen/dialogs_error.cpp +++ b/engines/xeen/dialogs_error.cpp @@ -82,4 +82,34 @@ void ErrorScroll::show(XeenEngine *vm, const Common::String &msg, ErrorWaitType ErrorDialog::show(vm, s, waitType); } +/*------------------------------------------------------------------------*/ + +void CantCast::show(XeenEngine *vm, int spellId, int componentNum) { + CantCast *dlg = new CantCast(vm); + dlg->execute(spellId, componentNum); + delete dlg; +} + +void CantCast::execute(int spellId, int componentNum) { + EventsManager &events = *_vm->_events; + SoundManager &sound = *_vm->_sound; + Window &w = _vm->_screen->_windows[6]; + Mode oldMode = _vm->_mode; + _vm->_mode = MODE_FF; + + sound.playFX(21); + w.open(); + w.writeString(Common::String::format(NOT_ENOUGH_TO_CAST, + SPELL_CAST_COMPONENTS[componentNum - 1])); + w.update(); + + do { + events.pollEventsAndWait(); + } while (!_vm->shouldQuit() && !events.isKeyMousePressed()); + events.clearEvents(); + + w.close(); + _vm->_mode = oldMode; +} + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_error.h b/engines/xeen/dialogs_error.h index 644b7e3b0e..46efdb1683 100644 --- a/engines/xeen/dialogs_error.h +++ b/engines/xeen/dialogs_error.h @@ -49,6 +49,17 @@ public: ErrorWaitType waitType = WT_FREEZE_WAIT); }; +class CantCast: public ButtonContainer { +private: + XeenEngine *_vm; + + CantCast(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + void execute(int spellId, int componentNum); +public: + static void show(XeenEngine *vm, int spellId, int componentNum); +}; + } // End of namespace Xeen #endif /* XEEN_DIALOGS_ERROR_H */ diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 0ce0259b45..fe249d263e 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -413,4 +413,146 @@ const char *SpellsScroll::setSpellText(Character *c, int v2) { return nullptr; } +/*------------------------------------------------------------------------*/ + +int CastSpell::show(XeenEngine *vm, int mode) { + Combat &combat = *vm->_combat; + Interface &intf = *vm->_interface; + Party &party = *vm->_party; + Spells &spells = *vm->_spells; + int charNum; + + // Get which character is doing the casting + if (mode == MODE_COMBAT) { + charNum = combat._whosTurn; + } else if (spells._lastCaster >= 0 && spells._lastCaster < (int)party._activeParty.size()) { + charNum = spells._lastCaster; + } else { + for (charNum = (int)party._activeParty.size() - 1; charNum >= 0; --charNum) { + if (party._activeParty[charNum]._hasSpells) { + spells._lastCaster = charNum; + break; + } + } + } + + Character &c = party._activeParty[charNum]; + intf.highlightChar(charNum); + + CastSpell *dlg = new CastSpell(vm); + int spellId = dlg->execute(&c, mode); + delete dlg; + + return spellId; +} + +int CastSpell::show(XeenEngine *vm, Character *c, int mode) { + CastSpell *dlg = new CastSpell(vm); + int spellId = dlg->execute(c, mode); + delete dlg; + + return spellId; +} + +int CastSpell::execute(Character *c, int mode) { + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + Spells &spells = *_vm->_spells; + Window &w = screen._windows[10]; + int charNum; + + Mode oldMode = (Mode)mode; + int category = c->getClassCategory(); + + w.open(); + loadButtons(); + drawButtons(&screen); + + int spellId = -1; + bool redrawFlag = true; + do { + if (redrawFlag) { + int spellIndex = c->_currentSpell != -1 ? c->_currentSpell : 39; + spellId = SPELLS_ALLOWED[category][spellIndex]; + int gemCost = SPELL_GEM_COST[spellId]; + int spCost = spells.calcSpellPoints(spellId, c->getCurrentLevel()); + + w.writeString(Common::String::format(CAST_SPELL_DETAILS, + c->_name.c_str(), spells._spellNames[spellId].c_str(), + spCost, gemCost, c->_currentSp)); + w.update(); + + _vm->_mode = MODE_3; + redrawFlag = false; + } + + events.updateGameCounter(); + intf.draw3d(true); + + // Wait for event or time expiry + do { + events.pollEventsAndWait(); + checkEvents(_vm); + } while (!_vm->shouldQuit() && events.timeElapsed() < 1 && !_buttonValue); + + switch (_buttonValue) { + case Common::KEYCODE_F1: + case Common::KEYCODE_F2: + case Common::KEYCODE_F3: + case Common::KEYCODE_F4: + case Common::KEYCODE_F5: + case Common::KEYCODE_F6: + // Only allow changing character if the party is not in combat + if (oldMode != MODE_COMBAT) { + _vm->_mode = oldMode; + _buttonValue -= Common::KEYCODE_F1; + + if (_buttonValue < (int)party._activeParty.size()) { + c = &party._activeParty[_buttonValue]; + intf.highlightChar(_buttonValue); + redrawFlag = true; + break; + } + } + break; + + case Common::KEYCODE_ESCAPE: + spellId = -1; + break; + + case Common::KEYCODE_c: + // Cast spell - return the selected spell Id to be cast + if (c->_currentSpell != -1 && !c->noActions()) + _buttonValue = Common::KEYCODE_ESCAPE; + break; + + case Common::KEYCODE_n: + // Select new spell + _vm->_mode = oldMode; + c = SpellsScroll::show(_vm, c, 1); + redrawFlag = true; + break; + + default: + break; + } + } while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE); + + w.close(); + intf.unhighlightChar(); + + return spellId; +} + +void CastSpell::loadButtons() { + _iconSprites.load("cast.icn"); + addButton(Common::Rect(234, 108, 259, 128), Common::KEYCODE_d, &_iconSprites); + addButton(Common::Rect(261, 108, 285, 128), Common::KEYCODE_w, &_iconSprites); + addButton(Common::Rect(288, 108, 312, 128), Common::KEYCODE_ESCAPE, &_iconSprites); + addPartyButtons(_vm); +} + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h index 69e339fa79..d0de44c932 100644 --- a/engines/xeen/dialogs_spells.h +++ b/engines/xeen/dialogs_spells.h @@ -56,6 +56,21 @@ public: static Character *show(XeenEngine *vm, Character *c, int v2); }; +class CastSpell : public ButtonContainer { +private: + XeenEngine *_vm; + SpriteResource _iconSprites; + + CastSpell(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + int execute(Character *c, int mode); + + void loadButtons(); +public: + static int show(XeenEngine *vm, int mode); + static int show(XeenEngine *vm, Character *c, int mode); +}; + } // End of namespace Xeen #endif /* XEEN_DIALOGS_SPELLS_H */ diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index a8396288ee..3bd3ef12b6 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -31,6 +31,7 @@ #include "xeen/dialogs_query.h" #include "xeen/dialogs_quests.h" #include "xeen/dialogs_quick_ref.h" +#include "xeen/dialogs_spells.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -267,6 +268,7 @@ void Interface::perform() { Map &map = *_vm->_map; Party &party = *_vm->_party; Scripts &scripts = *_vm->_scripts; + Spells &spells = *_vm->_spells; const Common::Rect waitBounds(8, 8, 224, 140); events.updateGameCounter(); @@ -517,6 +519,14 @@ void Interface::perform() { } break; + case Common::KEYCODE_c: { + // Cast spell + int spellId = CastSpell::show(_vm, _vm->_mode); + if (spellId != -1) + spells.castSpell(spellId); + break; + } + case Common::KEYCODE_i: // Show Info dialog _vm->_moveMonsters = false; @@ -585,8 +595,10 @@ void Interface::stepTime() { } void Interface::doStepCode() { + Combat &combat = *_vm->_combat; Map &map = *_vm->_map; Party &party = *_vm->_party; + Scripts &scripts = *_vm->_scripts; int damage = 0; party._stepped = true; @@ -642,8 +654,11 @@ void Interface::doStepCode() { _flipGround = !_flipGround; draw3d(true); - warning("TODO: apply damage"); + int oldVal = scripts._v2; + scripts._v2 = 0; + combat.giveCharDamage(damage, combat._damageType, 0); + scripts._v2 = oldVal; _flipGround = !_flipGround; } else if (party._partyDead) { draw3d(true); @@ -1825,6 +1840,7 @@ void Interface::doCombat() { Party &party = *_vm->_party; Screen &screen = *_vm->_screen; Scripts &scripts = *_vm->_scripts; + Spells &spells = *_vm->_spells; SoundManager &sound = *_vm->_sound; bool upDoorText = _upDoorText; bool reloadMap = false; @@ -1933,14 +1949,13 @@ void Interface::doCombat() { nextChar(); break; - case Common::KEYCODE_c: - // Cast Spell - if (combat.castSpell(false)) { - nextChar(); - } else { - highlightChar(combat._combatParty[combat._whosTurn]->_rosterId); - } + case Common::KEYCODE_c: { + // Cast spell + int spellId = CastSpell::show(_vm, _vm->_mode); + if (spellId != -1) + spells.castSpell(spellId); break; + } case Common::KEYCODE_f: // Quick Fight diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index c57b6a72cc..0fe20fb2c4 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1498,4 +1498,19 @@ const int NEW_CHARACTER_SPELLS[10][4] = { const char *const COMBAT_DETAILS = "\r\f00\x03c\v000\t000\x02Combat%s%s%s\x1"; +const char *NOT_ENOUGH_TO_CAST = "\x03c\v010Not enough %s to Cast %s"; +const char *SPELL_CAST_COMPONENTS[2] = { "Spell Points", "Gems" }; + +const char *const CAST_SPELL_DETAILS = + "\r\x2\x3""c\v122\t013\f37C\fdast\t040\f37N\fdew" + "\t067ESC\x1\t000\v000\x3""cCast Spell\n" + "\n" + "%s\x3l\n" + "\n" + "Spell Ready:\x3""c\n" + "\n" + "\f09%s\fd\x2\x3l\n" + "\v082Cost\x3r\t000%u/%u\x3l\n" + "Cur SP\x3r\t000%u\x1"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index d6902129e8..30eb4f5b63 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -524,6 +524,11 @@ extern const int NEW_CHARACTER_SPELLS[10][4]; extern const char *const COMBAT_DETAILS; +extern const char *NOT_ENOUGH_TO_CAST; +extern const char *SPELL_CAST_COMPONENTS[2]; + +extern const char *const CAST_SPELL_DETAILS; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 4943d95d2a..20ba480a6b 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -104,6 +104,37 @@ void Spells::doSpell(int spellId) { (this->*SPELL_LIST[spellId])(); } +void Spells::castSpell(int spellId) { + // TODO + error("TODO: castSpell"); +} + +/** + * Subtract the requirements for a given spell if available, returning + * true if there was sufficient + */ +int Spells::subSpellCost(Character &c, int spellId) { + Party &party = *_vm->_party; + int gemCost = SPELL_GEM_COST[spellId]; + int spCost = SPELL_COSTS[spellId]; + + // Negative SP costs indicate it's dependent on the character's level + if (spCost <= 0) { + spCost = c.getCurrentLevel() * (spCost * -1); + } + + if (spCost > c._currentSp) + // Not enough SP + return 1; + if (gemCost > party._gems) + // Not enough gems + return 2; + + c._currentSp -= spCost; + party._gems -= gemCost; + return 0; +} + void Spells::light() { error("TODO: spell"); } void Spells::awaken() { error("TODO: spell"); } void Spells::magicArrow() { error("TODO: spell"); } diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h index 15389be599..cffb302c51 100644 --- a/engines/xeen/spells.h +++ b/engines/xeen/spells.h @@ -29,6 +29,7 @@ namespace Xeen { class XeenEngine; +class Character; #define MAX_SPELLS_PER_CLASS 40 @@ -158,6 +159,10 @@ public: int calcSpellPoints(int spellId, int expenseFactor) const; void doSpell(int spellId); + + void castSpell(int spellId); + + int subSpellCost(Character &c, int spellId); }; } // End of namespace Xeen -- cgit v1.2.3 From 1d5d98e898cf132a102ef3b1953af31f53da79cc Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 17 Feb 2015 21:57:50 -0500 Subject: XEEN: Fix display of buttons in Cast Spell window --- engines/xeen/dialogs_spells.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index fe249d263e..8688ffe5a6 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -469,7 +469,6 @@ int CastSpell::execute(Character *c, int mode) { w.open(); loadButtons(); - drawButtons(&screen); int spellId = -1; bool redrawFlag = true; @@ -483,6 +482,7 @@ int CastSpell::execute(Character *c, int mode) { w.writeString(Common::String::format(CAST_SPELL_DETAILS, c->_name.c_str(), spells._spellNames[spellId].c_str(), spCost, gemCost, c->_currentSp)); + drawButtons(&screen); w.update(); _vm->_mode = MODE_3; -- cgit v1.2.3 From 6a7fd1952d62ce0bf44a426aba061ecc85183168 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 18 Feb 2015 08:11:57 -0500 Subject: XEEN: Fixes for display of Spells dialog --- engines/xeen/dialogs_spells.cpp | 119 +++++++++++++++++++++------------------- engines/xeen/dialogs_spells.h | 9 +-- engines/xeen/town.cpp | 4 +- 3 files changed, 70 insertions(+), 62 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 8688ffe5a6..7abca3fb85 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -29,15 +29,15 @@ namespace Xeen { -Character *SpellsScroll::show(XeenEngine *vm, Character *c, int v2) { - SpellsScroll *dlg = new SpellsScroll(vm); +Character *SpellsDialog::show(XeenEngine *vm, Character *c, int v2) { + SpellsDialog *dlg = new SpellsDialog(vm); Character *result = dlg->execute(c, v2); delete dlg; return result; } -Character *SpellsScroll::execute(Character *c, int v2) { +Character *SpellsDialog::execute(Character *c, int isCasting) { EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; Party &party = *_vm->_party; @@ -47,15 +47,15 @@ Character *SpellsScroll::execute(Character *c, int v2) { bool isDarkCc = _vm->_files->_isDarkCc; loadButtons(); - int v2Copy = v2; - v2 &= 0x7f; + int castingCopy = isCasting; + isCasting &= 0x7f; int selection = -1; uint topIndex = 0; int newSelection; screen._windows[25].open(); - while (!_vm->shouldQuit()) { - if (!v2) { + do { + if (!isCasting) { if (!c->guildMember()) { sound.playSample(nullptr, 0); intf._overallFrame = 5; @@ -73,38 +73,46 @@ Character *SpellsScroll::execute(Character *c, int v2) { } _spells.clear(); - const char *errorMsg = setSpellText(c, v2Copy); + const char *errorMsg = setSpellText(c, castingCopy); screen._windows[25].writeString(Common::String::format(SPELLS_FOR, - errorMsg == nullptr ? SPELL_LINES_0_TO_9 : nullptr)); + errorMsg == nullptr ? SPELL_LINES_0_TO_9 : nullptr, + c->_name.c_str())); + + // Setup and write out spell list + const char *names[10]; + int colors[10]; + Common::String emptyStr = ""; + Common::fill(&names[0], &names[10], emptyStr.c_str()); + Common::fill(&colors[0], &colors[10], 9); + + for (int idx = 0; idx < 10; ++idx) { + if ((topIndex + idx) < _spells.size()) { + names[idx] = _spells[topIndex + idx]._name.c_str(); + colors[idx] = _spells[topIndex + idx]._color; + } + } screen._windows[37].writeString(Common::String::format(SPELLS_DIALOG_SPELLS, - (topIndex + 0) < _spells.size() ? _spells[topIndex + 0]._name.c_str() : nullptr, - (topIndex + 1) < _spells.size() ? _spells[topIndex + 1]._name.c_str() : nullptr, - (topIndex + 2) < _spells.size() ? _spells[topIndex + 2]._name.c_str() : nullptr, - (topIndex + 3) < _spells.size() ? _spells[topIndex + 3]._name.c_str() : nullptr, - (topIndex + 4) < _spells.size() ? _spells[topIndex + 4]._name.c_str() : nullptr, - (topIndex + 5) < _spells.size() ? _spells[topIndex + 5]._name.c_str() : nullptr, - (topIndex + 6) < _spells.size() ? _spells[topIndex + 6]._name.c_str() : nullptr, - (topIndex + 7) < _spells.size() ? _spells[topIndex + 7]._name.c_str() : nullptr, - (topIndex + 8) < _spells.size() ? _spells[topIndex + 8]._name.c_str() : nullptr, - (topIndex + 9) < _spells.size() ? _spells[topIndex + 9]._name.c_str() : nullptr, - v2 ? SPELL_PTS : GOLD, - v2 ? c->_currentSp : party._gold + colors[0], names[0], colors[1], names[1], colors[2], names[2], + colors[3], names[3], colors[4], names[4], colors[5], names[5], + colors[6], names[6], colors[7], names[7], colors[8], names[8], + colors[9], names[9], + isCasting ? SPELL_PTS : GOLD, + isCasting ? c->_currentSp : party._gold )); - _iconSprites.draw(screen, 4, Common::Point(39, 26)); - _iconSprites.draw(screen, 0, Common::Point(187, 26)); - _iconSprites.draw(screen, 2, Common::Point(187, 111)); - if (v2) - _iconSprites.draw(screen._windows[25], 5, Common::Point(132, 123)); + _scrollSprites.draw(screen, 4, Common::Point(39, 26)); + _scrollSprites.draw(screen, 0, Common::Point(187, 26)); + _scrollSprites.draw(screen, 2, Common::Point(187, 111)); + if (isCasting) + _scrollSprites.draw(screen._windows[25], 5, Common::Point(132, 123)); screen._windows[25].update(); - while (!_vm->shouldQuit() && !events.isKeyMousePressed()) + do { events.pollEventsAndWait(); - if (_vm->shouldQuit()) - break; - checkEvents(_vm); + checkEvents(_vm); + } while (!_vm->shouldQuit() && !_buttonValue); switch (_buttonValue) { case Common::KEYCODE_F1: @@ -207,16 +215,16 @@ Character *SpellsScroll::execute(Character *c, int v2) { int spellId = _spells[newSelection]._spellId; int spellIndex = _spells[newSelection]._spellIndex; int spellCost = spells.calcSpellCost(spellId, expenseFactor); - if (v2) { + if (isCasting) { // TODO: Confirm this refactoring against against original selection = _buttonValue; } else { Common::String spellName = _spells[_buttonValue]._name; - Common::String msg = (v2Copy & 0x80) ? + Common::String msg = (castingCopy & 0x80) ? Common::String::format(SPELLS_PRESS_A_KEY, msg.c_str()) : Common::String::format(SPELLS_PURCHASE, msg.c_str(), spellCost); - if (Confirm::show(_vm, msg, v2Copy + 1)) { + if (Confirm::show(_vm, msg, castingCopy + 1)) { if (party.subtract(0, spellCost, 0, WT_FREEZE_WAIT)) { ++c->_spells[spellIndex]; sound.playSample(nullptr, 0); @@ -253,37 +261,38 @@ Character *SpellsScroll::execute(Character *c, int v2) { ++topIndex; break; } - } + } while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE); screen._windows[25].close(); - if (v2 && selection != -1) + if (isCasting && selection != -1) c->_currentSpell = _spells[selection]._spellIndex; return c; } -void SpellsScroll::loadButtons() { +void SpellsDialog::loadButtons() { _iconSprites.load("main.icn"); _scrollSprites.load("scroll.icn"); addButton(Common::Rect(187, 26, 198, 36), Common::KEYCODE_UP, &_scrollSprites, true); addButton(Common::Rect(187, 111, 198, 121), Common::KEYCODE_DOWN, &_scrollSprites, true); - addButton(Common::Rect(40, 28, 187, 36), Common::KEYCODE_1, &_scrollSprites, false); - addButton(Common::Rect(40, 37, 187, 45), Common::KEYCODE_2, &_scrollSprites, false); - addButton(Common::Rect(40, 46, 187, 54), Common::KEYCODE_3, &_scrollSprites, false); - addButton(Common::Rect(40, 55, 187, 63), Common::KEYCODE_4, &_scrollSprites, false); - addButton(Common::Rect(40, 64, 187, 72), Common::KEYCODE_5, &_scrollSprites, false); - addButton(Common::Rect(40, 73, 187, 81), Common::KEYCODE_6, &_scrollSprites, false); - addButton(Common::Rect(40, 82, 187, 90), Common::KEYCODE_7, &_scrollSprites, false); - addButton(Common::Rect(40, 91, 187, 99), Common::KEYCODE_8, &_scrollSprites, false); - addButton(Common::Rect(40, 100, 187, 108), Common::KEYCODE_9, &_scrollSprites, false); - addButton(Common::Rect(40, 109, 187, 117), Common::KEYCODE_0, &_scrollSprites, false); - addButton(Common::Rect(174, 123, 198, 133), Common::KEYCODE_ESCAPE, &_scrollSprites, false); - addButton(Common::Rect(187, 35, 198, 73), Common::KEYCODE_PAGEUP, &_scrollSprites, false); - addButton(Common::Rect(187, 74, 198, 112), Common::KEYCODE_PAGEDOWN, &_scrollSprites, false); - addButton(Common::Rect(132, 123, 168, 133), Common::KEYCODE_s, &_scrollSprites, false); + addButton(Common::Rect(40, 28, 187, 36), Common::KEYCODE_1); + addButton(Common::Rect(40, 37, 187, 45), Common::KEYCODE_2); + addButton(Common::Rect(40, 46, 187, 54), Common::KEYCODE_3); + addButton(Common::Rect(40, 55, 187, 63), Common::KEYCODE_4); + addButton(Common::Rect(40, 64, 187, 72), Common::KEYCODE_5); + addButton(Common::Rect(40, 73, 187, 81), Common::KEYCODE_6); + addButton(Common::Rect(40, 82, 187, 90), Common::KEYCODE_7); + addButton(Common::Rect(40, 91, 187, 99), Common::KEYCODE_8); + addButton(Common::Rect(40, 100, 187, 108), Common::KEYCODE_9); + addButton(Common::Rect(40, 109, 187, 117), Common::KEYCODE_0); + addButton(Common::Rect(174, 123, 198, 133), Common::KEYCODE_ESCAPE); + addButton(Common::Rect(187, 35, 198, 73), Common::KEYCODE_PAGEUP); + addButton(Common::Rect(187, 74, 198, 112), Common::KEYCODE_PAGEDOWN); + addButton(Common::Rect(132, 123, 168, 133), Common::KEYCODE_s); + addPartyButtons(_vm); } -const char *SpellsScroll::setSpellText(Character *c, int v2) { +const char *SpellsDialog::setSpellText(Character *c, int v2) { Party &party = *_vm->_party; Spells &spells = *_vm->_spells; bool isDarkCc = _vm->_files->_isDarkCc; @@ -459,10 +468,8 @@ int CastSpell::execute(Character *c, int mode) { Interface &intf = *_vm->_interface; Party &party = *_vm->_party; Screen &screen = *_vm->_screen; - SoundManager &sound = *_vm->_sound; Spells &spells = *_vm->_spells; Window &w = screen._windows[10]; - int charNum; Mode oldMode = (Mode)mode; int category = c->getClassCategory(); @@ -532,7 +539,7 @@ int CastSpell::execute(Character *c, int mode) { case Common::KEYCODE_n: // Select new spell _vm->_mode = oldMode; - c = SpellsScroll::show(_vm, c, 1); + c = SpellsDialog::show(_vm, c, 1); redrawFlag = true; break; @@ -549,8 +556,8 @@ int CastSpell::execute(Character *c, int mode) { void CastSpell::loadButtons() { _iconSprites.load("cast.icn"); - addButton(Common::Rect(234, 108, 259, 128), Common::KEYCODE_d, &_iconSprites); - addButton(Common::Rect(261, 108, 285, 128), Common::KEYCODE_w, &_iconSprites); + addButton(Common::Rect(234, 108, 259, 128), Common::KEYCODE_c, &_iconSprites); + addButton(Common::Rect(261, 108, 285, 128), Common::KEYCODE_n, &_iconSprites); addButton(Common::Rect(288, 108, 312, 128), Common::KEYCODE_ESCAPE, &_iconSprites); addPartyButtons(_vm); } diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h index d0de44c932..c27567cd5c 100644 --- a/engines/xeen/dialogs_spells.h +++ b/engines/xeen/dialogs_spells.h @@ -33,19 +33,20 @@ struct SpellEntry { Common::String _name; int _spellIndex; int _spellId; + int _color; SpellEntry(const Common::String &name, int spellIndex, int spellId) : - _name(name), _spellIndex(spellIndex), _spellId(spellId) {} + _name(name), _spellIndex(spellIndex), _spellId(spellId), _color(9) {} }; -class SpellsScroll : public ButtonContainer { +class SpellsDialog : public ButtonContainer { private: XeenEngine *_vm; SpriteResource _iconSprites; SpriteResource _scrollSprites; Common::Array<SpellEntry> _spells; - SpellsScroll(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + SpellsDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} Character *execute(Character *c, int v2); @@ -53,7 +54,7 @@ private: const char *setSpellText(Character *c, int v2); public: - static Character *show(XeenEngine *vm, Character *c, int v2); + static Character *show(XeenEngine *vm, Character *c, int isCasting); }; class CastSpell : public ButtonContainer { diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index f68a554b5f..b850439021 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -567,12 +567,12 @@ Character *Town::doGuildOptions(Character *c) { } } else if (_buttonValue == Common::KEYCODE_s) { if (c->guildMember()) - c = SpellsScroll::show(_vm, c, 0x80); + c = SpellsDialog::show(_vm, c, 0x80); _buttonValue = 0; } else if (_buttonValue == Common::KEYCODE_c) { if (!c->noActions()) { if (c->guildMember()) - c = SpellsScroll::show(_vm, c, 0); + c = SpellsDialog::show(_vm, c, 0); _buttonValue = 0; } } -- cgit v1.2.3 From 0f78fb9373b8c4befd727e9e56faf5d30ac59cff Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 18 Feb 2015 20:35:32 -0500 Subject: XEEN: Implement extra code for passing active character to castSpell --- engines/xeen/combat.cpp | 3 +- engines/xeen/dialogs_items.cpp | 2 +- engines/xeen/dialogs_spells.cpp | 18 ++++++----- engines/xeen/dialogs_spells.h | 4 +-- engines/xeen/interface.cpp | 28 ++++++++++++++--- engines/xeen/spells.cpp | 68 +++++++++++++++++++++++++++++++++++++---- engines/xeen/spells.h | 8 +++-- 7 files changed, 106 insertions(+), 25 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index b77ef6e95d..7ed349906d 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -721,7 +721,6 @@ void Combat::block() { void Combat::quickFight() { Spells &spells = *_vm->_spells; Character *c = _combatParty[_whosTurn]; - int spellId; switch (c->_quickOption) { case QUICK_ATTACK: @@ -729,7 +728,7 @@ void Combat::quickFight() { break; case QUICK_SPELL: if (c->_currentSpell != -1) { - spells.castSpell(SPELLS_ALLOWED[c->getClassCategory()][c->_currentSpell]); + spells.castSpell(c, SPELLS_ALLOWED[c->getClassCategory()][c->_currentSpell]); } break; case QUICK_BLOCK: diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index ec82afbbd2..f8131db0f1 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -889,7 +889,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite screen._windows[30].close(); screen._windows[29].close(); screen._windows[24].close(); - spells.doSpell(i._id); + spells.castItemSpell(i._id); if (!charges) { // Ran out of charges, so make item disappear diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 7abca3fb85..2f4026b2ad 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -29,9 +29,9 @@ namespace Xeen { -Character *SpellsDialog::show(XeenEngine *vm, Character *c, int v2) { +Character *SpellsDialog::show(XeenEngine *vm, Character *c, int isCasting) { SpellsDialog *dlg = new SpellsDialog(vm); - Character *result = dlg->execute(c, v2); + Character *result = dlg->execute(c, isCasting); delete dlg; return result; @@ -116,6 +116,10 @@ Character *SpellsDialog::execute(Character *c, int isCasting) { switch (_buttonValue) { case Common::KEYCODE_F1: + case Common::KEYCODE_F2: + case Common::KEYCODE_F3: + case Common::KEYCODE_F4: + case Common::KEYCODE_F5: case Common::KEYCODE_F6: if (_vm->_mode != MODE_COMBAT) { _buttonValue -= Common::KEYCODE_F1; @@ -143,7 +147,7 @@ Character *SpellsDialog::execute(Character *c, int isCasting) { break; } - int spellIndex = (c->_currentSp == -1) ? 39 : c->_currentSpell; + int spellIndex = (c->_currentSpell == -1) ? 39 : c->_currentSpell; int spellId = SPELLS_ALLOWED[category][spellIndex]; screen._windows[10].writeString(Common::String::format(SPELL_DETAILS, spells._spellNames[spellId].c_str(), @@ -445,17 +449,17 @@ int CastSpell::show(XeenEngine *vm, int mode) { } } - Character &c = party._activeParty[charNum]; + Character *c = &party._activeParty[charNum]; intf.highlightChar(charNum); CastSpell *dlg = new CastSpell(vm); - int spellId = dlg->execute(&c, mode); + int spellId = dlg->execute(c, mode); delete dlg; return spellId; } -int CastSpell::show(XeenEngine *vm, Character *c, int mode) { +int CastSpell::show(XeenEngine *vm, Character *&c, int mode) { CastSpell *dlg = new CastSpell(vm); int spellId = dlg->execute(c, mode); delete dlg; @@ -463,7 +467,7 @@ int CastSpell::show(XeenEngine *vm, Character *c, int mode) { return spellId; } -int CastSpell::execute(Character *c, int mode) { +int CastSpell::execute(Character *&c, int mode) { EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; Party &party = *_vm->_party; diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h index c27567cd5c..f091da66cf 100644 --- a/engines/xeen/dialogs_spells.h +++ b/engines/xeen/dialogs_spells.h @@ -64,12 +64,12 @@ private: CastSpell(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} - int execute(Character *c, int mode); + int execute(Character *&c, int mode); void loadButtons(); public: static int show(XeenEngine *vm, int mode); - static int show(XeenEngine *vm, Character *c, int mode); + static int show(XeenEngine *vm, Character *&c, int mode); }; } // End of namespace Xeen diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 3bd3ef12b6..7efc7a7068 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -521,9 +521,25 @@ void Interface::perform() { case Common::KEYCODE_c: { // Cast spell - int spellId = CastSpell::show(_vm, _vm->_mode); - if (spellId != -1) - spells.castSpell(spellId); + if (_tillMove) { + combat.moveMonsters(); + draw3d(true); + } + + int result = 0; + do { + Character *c = nullptr; + int spellId = CastSpell::show(_vm, c, _vm->_mode); + if (spellId == -1 || c == nullptr) + break; + + result = spells.castSpell(c, spellId); + } while (result != -1); + + if (result == 1) { + chargeStep(); + doStepCode(); + } break; } @@ -1952,8 +1968,10 @@ void Interface::doCombat() { case Common::KEYCODE_c: { // Cast spell int spellId = CastSpell::show(_vm, _vm->_mode); - if (spellId != -1) - spells.castSpell(spellId); + if (spellId != -1) { + Character *c = combat._combatParty[combat._whosTurn]; + spells.castSpell(c, spellId); + } break; } diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 20ba480a6b..3b753bc90b 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -53,7 +53,7 @@ int Spells::calcSpellPoints(int spellId, int expenseFactor) const { typedef void(Spells::*SpellMethodPtr)(); -void Spells::doSpell(int spellId) { +void Spells::executeSpell(int spellId) { static const SpellMethodPtr SPELL_LIST[73] = { &Spells::light, &Spells::awaken, &Spells::magicArrow, &Spells::firstAid, &Spells::flyingFist, &Spells::energyBlast, &Spells::sleep, @@ -92,6 +92,10 @@ void Spells::doSpell(int spellId) { &Spells::implosion, &Spells::starBurst, &Spells::divineIntervention }; + (this->*SPELL_LIST[spellId])(); +} + +void Spells::castItemSpell(int spellId) { if (_vm->_mode == MODE_COMBAT) { if (spellId == 15 || spellId == 20 || spellId == 27 || spellId == 41 || spellId == 47 || spellId == 54 || spellId == 57) { @@ -101,12 +105,47 @@ void Spells::doSpell(int spellId) { } } - (this->*SPELL_LIST[spellId])(); + executeSpell(spellId); } -void Spells::castSpell(int spellId) { - // TODO - error("TODO: castSpell"); +/** + * Cast a given spell + */ +int Spells::castSpell(Character *c, int spellId) { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + int oldTillMove = intf._tillMove; + int result = 1; + combat._oldCharacter = c; + + // Try and subtract the SP and gem requirements for the spell + int resultError = subSpellCost(*c, spellId); + if (resultError) { + CantCast::show(_vm, spellId, resultError); + result = -1; + } else { + // Some spells have special handling + switch (spellId) { + case 19: + // Enchant item + if (_vm->_mode != MODE_COMBAT) { + enchantItem(); + } else { + // Return the spell costs and flag that another spell can be selected + addSpellCost(*c, spellId); + result = -1; + } + break; + + default: + executeSpell(spellId); + break; + } + } + + _vm->_moveMonsters = 1; + intf._tillMove = oldTillMove; + return result; } /** @@ -126,7 +165,7 @@ int Spells::subSpellCost(Character &c, int spellId) { if (spCost > c._currentSp) // Not enough SP return 1; - if (gemCost > party._gems) + if (gemCost > (int)party._gems) // Not enough gems return 2; @@ -135,6 +174,23 @@ int Spells::subSpellCost(Character &c, int spellId) { return 0; } +/** + * Add the SP and gem requirements for a given spell to the given + * character and party + */ +void Spells::addSpellCost(Character &c, int spellId) { + Party &party = *_vm->_party; + int gemCost = SPELL_GEM_COST[spellId]; + int spCost = SPELL_COSTS[spellId]; + + if (spCost < 1) + spCost *= -1 * c.getCurrentLevel(); + + c._currentSp += spCost; + party._gems += gemCost; +} + + void Spells::light() { error("TODO: spell"); } void Spells::awaken() { error("TODO: spell"); } void Spells::magicArrow() { error("TODO: spell"); } diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h index cffb302c51..af52511efa 100644 --- a/engines/xeen/spells.h +++ b/engines/xeen/spells.h @@ -67,6 +67,8 @@ private: void load(); + void executeSpell(int spellId); + // Spell list void light(); void awaken(); @@ -158,11 +160,13 @@ public: int calcSpellPoints(int spellId, int expenseFactor) const; - void doSpell(int spellId); + void castItemSpell(int spellId); - void castSpell(int spellId); + int castSpell(Character *c, int spellId); int subSpellCost(Character &c, int spellId); + + void addSpellCost(Character &c, int spellId); }; } // End of namespace Xeen -- cgit v1.2.3 From da368f5e008795168daa98dace83d6510100d8bc Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 18 Feb 2015 21:17:55 -0500 Subject: XEEN: Add special case spell handling during combat --- engines/xeen/interface.cpp | 4 +++- engines/xeen/spells.cpp | 14 +++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 7efc7a7068..0c7f15dc5f 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -527,8 +527,10 @@ void Interface::perform() { } int result = 0; + Character *c = &party._activeParty[(spells._lastCaster < 0 || + spells._lastCaster >= (int)party._activeParty.size()) ? + (int)party._activeParty.size() - 1 : spells._lastCaster]; do { - Character *c = nullptr; int spellId = CastSpell::show(_vm, c, _vm->_mode); if (spellId == -1 || c == nullptr) break; diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 3b753bc90b..d2a2af31c0 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -126,13 +126,21 @@ int Spells::castSpell(Character *c, int spellId) { } else { // Some spells have special handling switch (spellId) { - case 19: - // Enchant item + case 19: // Enchant item + case 21: // Etherialize + case 40: // Jump + case 44: // Lloyd's Beacon + case 66: // Super Shelter + case 69: // Teleport + case 71: // Town Portal + case 75: // Wizard Eye if (_vm->_mode != MODE_COMBAT) { - enchantItem(); + executeSpell(spellId); } else { // Return the spell costs and flag that another spell can be selected addSpellCost(*c, spellId); + ErrorDialog::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED, + _spellNames[spellId])); result = -1; } break; -- cgit v1.2.3 From aa89e602a2d261a24861bf65877bba3fab647409 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 18 Feb 2015 21:42:57 -0500 Subject: XEEN: Spell dialogs fixes for non-casters --- engines/xeen/dialogs_spells.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 2f4026b2ad..dbe48c1a99 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -75,7 +75,7 @@ Character *SpellsDialog::execute(Character *c, int isCasting) { _spells.clear(); const char *errorMsg = setSpellText(c, castingCopy); screen._windows[25].writeString(Common::String::format(SPELLS_FOR, - errorMsg == nullptr ? SPELL_LINES_0_TO_9 : nullptr, + errorMsg == nullptr ? SPELL_LINES_0_TO_9 : "", c->_name.c_str())); // Setup and write out spell list @@ -92,6 +92,9 @@ Character *SpellsDialog::execute(Character *c, int isCasting) { } } + if (_spells.size() == 0) + names[0] = errorMsg; + screen._windows[37].writeString(Common::String::format(SPELLS_DIALOG_SPELLS, colors[0], names[0], colors[1], names[1], colors[2], names[2], colors[3], names[3], colors[4], names[4], colors[5], names[5], @@ -150,7 +153,7 @@ Character *SpellsDialog::execute(Character *c, int isCasting) { int spellIndex = (c->_currentSpell == -1) ? 39 : c->_currentSpell; int spellId = SPELLS_ALLOWED[category][spellIndex]; screen._windows[10].writeString(Common::String::format(SPELL_DETAILS, - spells._spellNames[spellId].c_str(), + c->_name.c_str(), spells._spellNames[spellId].c_str(), spells.calcSpellPoints(spellId, c->getCurrentLevel()), SPELL_GEM_COST[spellId], c->_currentSp)); } @@ -555,6 +558,9 @@ int CastSpell::execute(Character *&c, int mode) { w.close(); intf.unhighlightChar(); + if (_vm->shouldQuit()) + spellId = -1; + return spellId; } -- cgit v1.2.3 From cd5bc0ec7ec7652a39d550aea4f387eec45fa382 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 18 Feb 2015 22:05:25 -0500 Subject: XEEN: Simplify use of addButton when setting up button lists --- engines/xeen/dialogs.cpp | 11 +++++--- engines/xeen/dialogs.h | 5 ++-- engines/xeen/dialogs_dismiss.cpp | 8 +++--- engines/xeen/dialogs_exchange.cpp | 10 ++++---- engines/xeen/dialogs_items.cpp | 54 +++++++++++++++++++-------------------- engines/xeen/dialogs_options.cpp | 16 ++++++------ engines/xeen/dialogs_party.cpp | 18 ++++++------- engines/xeen/dialogs_spells.cpp | 6 ++--- engines/xeen/interface.cpp | 8 +++--- engines/xeen/resources.cpp | 12 --------- engines/xeen/resources.h | 2 -- engines/xeen/town.cpp | 46 ++++++++++++++++----------------- 12 files changed, 94 insertions(+), 102 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index 8bb0af0833..116054dfe7 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -47,14 +47,19 @@ void ButtonContainer::restoreButtons() { _buttons = _savedButtons.pop(); } -void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw) { - _buttons.push_back(UIButton(bounds, val, sprites, draw)); +void ButtonContainer::addButton(const Common::Rect &bounds, int val, + SpriteResource *sprites) { + _buttons.push_back(UIButton(bounds, val, sprites, true)); +} + +void ButtonContainer::addButton(const Common::Rect &bounds, int val) { + _buttons.push_back(UIButton(bounds, val, nullptr, false)); } void ButtonContainer::addPartyButtons(XeenEngine *vm) { for (uint idx = 0; idx < MAX_ACTIVE_PARTY; ++idx) { addButton(Common::Rect(CHAR_FACES_X[idx], 150, CHAR_FACES_X[idx] + 32, 182), - Common::KEYCODE_F1 + idx, nullptr, false); + Common::KEYCODE_F1 + idx); } } diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h index 02e945b665..e2d8bc929c 100644 --- a/engines/xeen/dialogs.h +++ b/engines/xeen/dialogs.h @@ -66,8 +66,9 @@ public: void restoreButtons(); - void addButton(const Common::Rect &bounds, int val, - SpriteResource *sprites = nullptr, bool draw = true); + void addButton(const Common::Rect &bounds, int val, SpriteResource *sprites); + + void addButton(const Common::Rect &bounds, int val); void addPartyButtons(XeenEngine *vm); }; diff --git a/engines/xeen/dialogs_dismiss.cpp b/engines/xeen/dialogs_dismiss.cpp index 0c28affa6c..1317d84447 100644 --- a/engines/xeen/dialogs_dismiss.cpp +++ b/engines/xeen/dialogs_dismiss.cpp @@ -88,10 +88,10 @@ void Dismiss::execute() { void Dismiss::loadButtons() { _iconSprites.load("esc.icn"); addButton(Common::Rect(225, 120, 249, 140), Common::KEYCODE_ESCAPE, &_iconSprites); - addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_iconSprites, false); - addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_iconSprites, false); - addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3, &_iconSprites, false); - addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4, &_iconSprites, false); + addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1); + addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2); + addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3); + addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4); } } // End of namespace Xeen diff --git a/engines/xeen/dialogs_exchange.cpp b/engines/xeen/dialogs_exchange.cpp index 0b1e538b38..37da4e0963 100644 --- a/engines/xeen/dialogs_exchange.cpp +++ b/engines/xeen/dialogs_exchange.cpp @@ -70,11 +70,11 @@ void ExchangeDialog::execute(Character *&c, int &charIndex) { void ExchangeDialog::loadButtons() { _iconSprites.load("esc.icn"); - addButton(Common::Rect(225, 120, 249, 245), Common::KEYCODE_ESCAPE, &_iconSprites, true); - addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_iconSprites, false); - addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_iconSprites, false); - addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3, &_iconSprites, false); - addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4, &_iconSprites, false); + addButton(Common::Rect(225, 120, 249, 245), Common::KEYCODE_ESCAPE, &_iconSprites); + addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1); + addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2); + addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3); + addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4); } } // End of namespace Xeen diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index f8131db0f1..21a8856e3c 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -530,15 +530,15 @@ void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) { addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_e, &_iconSprites); addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites); addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_u, &_iconSprites); - addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1, &_iconSprites, false); - addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2, &_iconSprites, false); - addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3, &_iconSprites, false); - addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4, &_iconSprites, false); - addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5, &_iconSprites, false); - addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6, &_iconSprites, false); - addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, &_iconSprites, false); - addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, &_iconSprites, false); - addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, &_iconSprites, false); + addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1); + addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2); + addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3); + addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4); + addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5); + addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6); + addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7); + addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8); + addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9); } else { addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_w, &_iconSprites); addButton(Common::Rect(46, 109, 70, 129), Common::KEYCODE_a, &_iconSprites); @@ -549,15 +549,15 @@ void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) { addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_d, &_iconSprites); addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_q, &_iconSprites); addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites); - addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1, &_iconSprites, false); - addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2, &_iconSprites, false); - addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3, &_iconSprites, false); - addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4, &_iconSprites, false); - addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5, &_iconSprites, false); - addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6, &_iconSprites, false); - addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, &_iconSprites, false); - addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, &_iconSprites, false); - addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, &_iconSprites, false); + addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1); + addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2); + addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3); + addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4); + addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5); + addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6); + addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7); + addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8); + addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9); addPartyButtons(_vm); } @@ -807,15 +807,15 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite escSprites.load("esc.icn"); addButton(Common::Rect(235, 111, 259, 131), Common::KEYCODE_ESCAPE, &escSprites); - addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1, &escSprites, false); - addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2, &escSprites, false); - addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3, &escSprites, false); - addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4, &escSprites, false); - addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5, &escSprites, false); - addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6, &escSprites, false); - addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, &escSprites, false); - addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, &escSprites, false); - addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, &escSprites, false); + addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1); + addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2); + addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3); + addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4); + addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5); + addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6); + addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7); + addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8); + addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9); w.open(); w.writeString(Common::String::format(WHICH_ITEM, ITEM_ACTIONS[actionIndex])); diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp index 8f02559837..4b4974b9aa 100644 --- a/engines/xeen/dialogs_options.cpp +++ b/engines/xeen/dialogs_options.cpp @@ -155,17 +155,17 @@ void OptionsMenu::showTitles2() { } void OptionsMenu::setupButtons(SpriteResource *buttons) { - addButton(Common::Rect(124, 87, 124 + 53, 87 + 10), 'S', buttons, false); - addButton(Common::Rect(126, 98, 126 + 47, 98 + 10), 'L', buttons, false); - addButton(Common::Rect(91, 110, 91 + 118, 110 + 10), 'C', buttons, false); - addButton(Common::Rect(85, 121, 85 + 131, 121 + 10), 'O', buttons, false); + addButton(Common::Rect(124, 87, 124 + 53, 87 + 10), 'S'); + addButton(Common::Rect(126, 98, 126 + 47, 98 + 10), 'L'); + addButton(Common::Rect(91, 110, 91 + 118, 110 + 10), 'C'); + addButton(Common::Rect(85, 121, 85 + 131, 121 + 10), 'O'); } void WorldOptionsMenu::setupButtons(SpriteResource *buttons) { - addButton(Common::Rect(93, 53, 93 + 134, 53 + 20), 'S', buttons, true); - addButton(Common::Rect(93, 78, 93 + 134, 78 + 20), 'L', buttons, true); - addButton(Common::Rect(93, 103, 93 + 134, 103 + 20), 'C', buttons, true); - addButton(Common::Rect(93, 128, 93 + 134, 128 + 20), 'O', buttons, true); + addButton(Common::Rect(93, 53, 93 + 134, 53 + 20), 'S', buttons); + addButton(Common::Rect(93, 78, 93 + 134, 78 + 20), 'L', buttons); + addButton(Common::Rect(93, 103, 93 + 134, 103 + 20), 'C', buttons); + addButton(Common::Rect(93, 128, 93 + 134, 128 + 20), 'O', buttons); } /*------------------------------------------------------------------------*/ diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index 7414ce3404..544c110c82 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -280,7 +280,7 @@ void PartyDialog::loadButtons() { addButton(Common::Rect(122, 100, 146, 120), Common::KEYCODE_r, &_uiSprites); addButton(Common::Rect(157, 100, 181, 120), Common::KEYCODE_c, &_uiSprites); addButton(Common::Rect(192, 100, 216, 120), Common::KEYCODE_x, &_uiSprites); - addButton(Common::Rect(0, 0, 0, 0), Common::KEYCODE_ESCAPE, &_uiSprites, false); + addButton(Common::Rect(0, 0, 0, 0), Common::KEYCODE_ESCAPE); } void PartyDialog::initDrawStructs() { @@ -310,10 +310,10 @@ void PartyDialog::setupFaces(int firstDisplayChar, bool updateFlag) { // Reset the button areas for the display character images while (_buttons.size() > 7) _buttons.remove_at(7); - addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_uiSprites, false); - addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_uiSprites, false); - addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3, &_uiSprites, false); - addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4, &_uiSprites, false); + addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1); + addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2); + addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3); + addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4); for (posIndex = 0; posIndex < 4; ++posIndex) { @@ -712,10 +712,10 @@ int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) { saveButtons(); addButton(Common::Rect(225, isDelete ? 120 : 84, 249, isDelete ? 140 : 104), Common::KEYCODE_ESCAPE, &iconSprites); - addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &iconSprites, false); - addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &iconSprites, false); - addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3, &iconSprites, false); - addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4, &iconSprites, false); + addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1); + addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2); + addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3); + addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4); addPartyButtons(_vm); int result = -1, v; diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index dbe48c1a99..6a8b160dd8 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -152,7 +152,7 @@ Character *SpellsDialog::execute(Character *c, int isCasting) { int spellIndex = (c->_currentSpell == -1) ? 39 : c->_currentSpell; int spellId = SPELLS_ALLOWED[category][spellIndex]; - screen._windows[10].writeString(Common::String::format(SPELL_DETAILS, + screen._windows[10].writeString(Common::String::format(CAST_SPELL_DETAILS, c->_name.c_str(), spells._spellNames[spellId].c_str(), spells.calcSpellPoints(spellId, c->getCurrentLevel()), SPELL_GEM_COST[spellId], c->_currentSp)); @@ -280,8 +280,8 @@ Character *SpellsDialog::execute(Character *c, int isCasting) { void SpellsDialog::loadButtons() { _iconSprites.load("main.icn"); _scrollSprites.load("scroll.icn"); - addButton(Common::Rect(187, 26, 198, 36), Common::KEYCODE_UP, &_scrollSprites, true); - addButton(Common::Rect(187, 111, 198, 121), Common::KEYCODE_DOWN, &_scrollSprites, true); + addButton(Common::Rect(187, 26, 198, 36), Common::KEYCODE_UP, &_scrollSprites); + addButton(Common::Rect(187, 111, 198, 121), Common::KEYCODE_DOWN, &_scrollSprites); addButton(Common::Rect(40, 28, 187, 36), Common::KEYCODE_1); addButton(Common::Rect(40, 37, 187, 45), Common::KEYCODE_2); addButton(Common::Rect(40, 46, 187, 54), Common::KEYCODE_3); diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 0c7f15dc5f..04206581ec 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -239,10 +239,10 @@ void Interface::setMainButtons(bool combatMode) { addButton(Common::Rect(235, 169, 259, 189), (Common::KBD_CTRL << 16) |Common::KEYCODE_LEFT, &_iconSprites); addButton(Common::Rect(260, 169, 284, 189), Common::KEYCODE_DOWN, &_iconSprites); addButton(Common::Rect(286, 169, 310, 189), (Common::KBD_CTRL << 16) | Common::KEYCODE_RIGHT, &_iconSprites); - addButton(Common::Rect(236, 11, 308, 69), Common::KEYCODE_EQUALS, &_iconSprites, false); - addButton(Common::Rect(239, 27, 312, 37), Common::KEYCODE_1, &_iconSprites, false); - addButton(Common::Rect(239, 37, 312, 47), Common::KEYCODE_2, &_iconSprites, false); - addButton(Common::Rect(239, 47, 312, 57), Common::KEYCODE_3, &_iconSprites, false); + addButton(Common::Rect(236, 11, 308, 69), Common::KEYCODE_EQUALS); + addButton(Common::Rect(239, 27, 312, 37), Common::KEYCODE_1); + addButton(Common::Rect(239, 37, 312, 47), Common::KEYCODE_2); + addButton(Common::Rect(239, 47, 312, 57), Common::KEYCODE_3); addPartyButtons(_vm); if (combatMode) { diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 0fe20fb2c4..da57a8085b 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -931,18 +931,6 @@ const char *const SPELLS_PURCHASE = "\x3l\xB""000\x9""000\xC""d%s Do you wish to purchase " "\xC""09%s\xC""d for %u?"; -const char *const SPELL_DETAILS = - "\xD\x2\x3""c\xB""122\x9""013\xC""37C\xC""dast" - "\x9""040\xC""37N\xC""dew\x9""067ESC\x1""000\xB""000\x3""cCast Spell\n" - "\n" - "%s\x3l\n" - "\n" - "Spell Ready:\x3""c\n" - "\n" - "\xC""09%s\xC""d\x2\x3l\n" - "\xB""082Cost\x3r\x9""000%u/%u\x3l\n" - "Cur SP\x3r\x9""000%u\x1"; - const char *const MAP_TEXT = "\x3""c\xB""000\x9""000%s\x3l\xB""139" "\x9""000X = %d\x3r\x9""000Y = %d\x3""c\x9""000%s"; diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 30eb4f5b63..c61784475c 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -288,8 +288,6 @@ extern const char *const SPELLS_PRESS_A_KEY; extern const char *const SPELLS_PURCHASE; -extern const char *const SPELL_DETAILS; - extern const char *const MAP_TEXT; extern const char *const LIGHT_COUNT_TEXT; diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index b850439021..2723226996 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -108,11 +108,11 @@ int Town::townAction(int actionId) { case 1: // Blacksmith _icons1.load("esc.icn"); - addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1, true); - addButton(Common::Rect(234, 54, 308, 62), 0, &_icons1, false); - addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_b, &_icons1, false); - addButton(Common::Rect(234, 74, 308, 82), 0, &_icons1, false); - addButton(Common::Rect(234, 84, 308, 92), 0, &_icons1, false); + addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1); + addButton(Common::Rect(234, 54, 308, 62), 0); + addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_b); + addButton(Common::Rect(234, 74, 308, 82), 0); + addButton(Common::Rect(234, 84, 308, 92), 0); sound.playSample(nullptr, 0); vocName = isDarkCc ? "see2.voc" : "whaddayo.voc"; @@ -122,11 +122,11 @@ int Town::townAction(int actionId) { // Guild loadStrings("spldesc.bin"); _icons1.load("esc.icn"); - addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1, true); - addButton(Common::Rect(234, 54, 308, 62), 0, &_icons1, false); - addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_b, &_icons1, false); - addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_s, &_icons1, false); - addButton(Common::Rect(234, 84, 308, 92), 0, &_icons1, false); + addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1); + addButton(Common::Rect(234, 54, 308, 62), 0); + addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_b); + addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_s); + addButton(Common::Rect(234, 84, 308, 92), 0); _vm->_mode = MODE_17; sound.playSample(nullptr, 0); @@ -137,12 +137,12 @@ int Town::townAction(int actionId) { // Tavern loadStrings("tavern.bin"); _icons1.load("tavern.icn"); - addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons1, true); - addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_s, &_icons1, true); - addButton(Common::Rect(234, 54, 308, 62), Common::KEYCODE_d, &_icons1, false); - addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_f, &_icons1, false); - addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_t, &_icons1, false); - addButton(Common::Rect(234, 84, 308, 92), Common::KEYCODE_r, &_icons1, false); + addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons1); + addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_s, &_icons1); + addButton(Common::Rect(234, 54, 308, 62), Common::KEYCODE_d); + addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_f); + addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_t); + addButton(Common::Rect(234, 84, 308, 92), Common::KEYCODE_r); _vm->_mode = MODE_17; sound.playSample(nullptr, 0); @@ -152,11 +152,11 @@ int Town::townAction(int actionId) { case 4: // Temple _icons1.load("esc.icn"); - addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1, true); - addButton(Common::Rect(234, 54, 308, 62), Common::KEYCODE_h, &_icons1, false); - addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_d, &_icons1, false); - addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_u, &_icons1, false); - addButton(Common::Rect(234, 84, 308, 92), 0, &_icons1, false); + addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1); + addButton(Common::Rect(234, 54, 308, 62), Common::KEYCODE_h); + addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_d); + addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_u); + addButton(Common::Rect(234, 84, 308, 92), 0); sound.playSample(nullptr, 0); vocName = isDarkCc ? "help2.voc" : "maywe2.voc"; @@ -168,8 +168,8 @@ int Town::townAction(int actionId) { _v2 = 0; _icons1.load("train.icn"); - addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons1, true); - addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t, &_icons1, false); + addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons1); + addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t); sound.playSample(nullptr, 0); vocName = isDarkCc ? "training.voc" : "youtrn1.voc"; -- cgit v1.2.3 From 4c420a70be9124c224723a787d2335053f4986fe Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 18 Feb 2015 22:11:59 -0500 Subject: XEEN: Fix drawing buttons in Spells dialog when switching character --- engines/xeen/dialogs.h | 4 ++-- engines/xeen/dialogs_spells.cpp | 24 +++++++++++++----------- engines/xeen/dialogs_spells.h | 7 ++++--- engines/xeen/town.cpp | 4 ++-- 4 files changed, 21 insertions(+), 18 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h index e2d8bc929c..c04b680ff1 100644 --- a/engines/xeen/dialogs.h +++ b/engines/xeen/dialogs.h @@ -55,8 +55,6 @@ protected: void doScroll(XeenEngine *vm, bool drawFlag, bool doFade); bool checkEvents(XeenEngine *vm); - - void drawButtons(XSurface *surface); public: ButtonContainer() : _buttonValue(0) {} @@ -71,6 +69,8 @@ public: void addButton(const Common::Rect &bounds, int val); void addPartyButtons(XeenEngine *vm); + + void drawButtons(XSurface *surface); }; class SettingsBaseDialog : public ButtonContainer { diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 6a8b160dd8..e25d839a12 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -29,15 +29,16 @@ namespace Xeen { -Character *SpellsDialog::show(XeenEngine *vm, Character *c, int isCasting) { +Character *SpellsDialog::show(XeenEngine *vm, ButtonContainer *priorDialog, + Character *c, int isCasting) { SpellsDialog *dlg = new SpellsDialog(vm); - Character *result = dlg->execute(c, isCasting); + Character *result = dlg->execute(priorDialog, c, isCasting); delete dlg; return result; } -Character *SpellsDialog::execute(Character *c, int isCasting) { +Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int isCasting) { EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; Party &party = *_vm->_party; @@ -158,7 +159,8 @@ Character *SpellsDialog::execute(Character *c, int isCasting) { SPELL_GEM_COST[spellId], c->_currentSp)); } - drawButtons(&screen); + if (priorDialog != nullptr) + priorDialog->drawButtons(&screen); screen._windows[10].update(); } } @@ -299,7 +301,7 @@ void SpellsDialog::loadButtons() { addPartyButtons(_vm); } -const char *SpellsDialog::setSpellText(Character *c, int v2) { +const char *SpellsDialog::setSpellText(Character *c, int isCasting) { Party &party = *_vm->_party; Spells &spells = *_vm->_spells; bool isDarkCc = _vm->_files->_isDarkCc; @@ -307,7 +309,7 @@ const char *SpellsDialog::setSpellText(Character *c, int v2) { int currLevel = c->getCurrentLevel(); int category; - if ((v2 & 0x7f) == 0) { + if ((isCasting & 0x7f) == 0) { switch (c->_class) { case CLASS_PALADIN: expenseFactor = 1; @@ -344,7 +346,7 @@ const char *SpellsDialog::setSpellText(Character *c, int v2) { // Handling if the spell is appropriate for the character's class if (idx < MAX_SPELLS_PER_CLASS) { - if (!c->_spells[idx] || (v2 & 0x80)) { + if (!c->_spells[idx] || (isCasting & 0x80)) { int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor); _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u", spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), @@ -361,7 +363,7 @@ const char *SpellsDialog::setSpellText(Character *c, int v2) { DARK_SPELL_OFFSETS[category][spellId]); if (idx < 40) { - if (!c->_spells[idx] || (v2 & 0x80)) { + if (!c->_spells[idx] || (isCasting & 0x80)) { int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor); _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u", spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), @@ -376,7 +378,7 @@ const char *SpellsDialog::setSpellText(Character *c, int v2) { (int)SPELLS_ALLOWED[category][idx] && idx < 40) ; if (idx < 40) { - if (!c->_spells[idx] || (v2 & 0x80)) { + if (!c->_spells[idx] || (isCasting & 0x80)) { int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor); _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u", spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), @@ -390,7 +392,7 @@ const char *SpellsDialog::setSpellText(Character *c, int v2) { if (c->getMaxSP() == 0) return NOT_A_SPELL_CASTER; - } else if ((v2 & 0x7f) == 1) { + } else if ((isCasting & 0x7f) == 1) { switch (c->_class) { case 0: case 12: @@ -546,7 +548,7 @@ int CastSpell::execute(Character *&c, int mode) { case Common::KEYCODE_n: // Select new spell _vm->_mode = oldMode; - c = SpellsDialog::show(_vm, c, 1); + c = SpellsDialog::show(_vm, this, c, 1); redrawFlag = true; break; diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h index f091da66cf..32d079023d 100644 --- a/engines/xeen/dialogs_spells.h +++ b/engines/xeen/dialogs_spells.h @@ -48,13 +48,14 @@ private: SpellsDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} - Character *execute(Character *c, int v2); + Character *execute(ButtonContainer *priorDialog, Character *c, int isCasting); void loadButtons(); - const char *setSpellText(Character *c, int v2); + const char *setSpellText(Character *c, int isCasting); public: - static Character *show(XeenEngine *vm, Character *c, int isCasting); + static Character *show(XeenEngine *vm, ButtonContainer *priorDialog, + Character *c, int isCasting); }; class CastSpell : public ButtonContainer { diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 2723226996..3a8b6d8231 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -567,12 +567,12 @@ Character *Town::doGuildOptions(Character *c) { } } else if (_buttonValue == Common::KEYCODE_s) { if (c->guildMember()) - c = SpellsDialog::show(_vm, c, 0x80); + c = SpellsDialog::show(_vm, nullptr, c, 0x80); _buttonValue = 0; } else if (_buttonValue == Common::KEYCODE_c) { if (!c->noActions()) { if (c->guildMember()) - c = SpellsDialog::show(_vm, c, 0); + c = SpellsDialog::show(_vm, nullptr, c, 0); _buttonValue = 0; } } -- cgit v1.2.3 From e17d258217f8605d7722927cd0180b59f87717a5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 19 Feb 2015 07:57:25 -0500 Subject: XEEN: Fix display of spell names in Spells dialog --- engines/xeen/dialogs_spells.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index e25d839a12..5084843319 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -394,18 +394,16 @@ const char *SpellsDialog::setSpellText(Character *c, int isCasting) { } else if ((isCasting & 0x7f) == 1) { switch (c->_class) { - case 0: - case 12: - category = 0; - break; - case 1: - case 3: + case CLASS_ARCHER: + case CLASS_SORCERER: category = 1; break; - case 7: - case 8: + case CLASS_DRUID: + case CLASS_RANGER: category = 2; break; + case CLASS_PALADIN: + case CLASS_CLERIC: default: category = 0; break; -- cgit v1.2.3 From 7c3f373b9b935b71b3006f203a1f75442818673a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 19 Feb 2015 08:26:55 -0500 Subject: XEEN: Fix selecting spells to cast in spells dialog --- engines/xeen/dialogs_spells.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 5084843319..0383886c4d 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -93,6 +93,8 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int } } + if (selection >= topIndex && selection < (topIndex + 10)) + colors[selection - topIndex] = 15; if (_spells.size() == 0) names[0] = errorMsg; @@ -225,10 +227,9 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int int spellIndex = _spells[newSelection]._spellIndex; int spellCost = spells.calcSpellCost(spellId, expenseFactor); if (isCasting) { - // TODO: Confirm this refactoring against against original - selection = _buttonValue; + selection = newSelection; } else { - Common::String spellName = _spells[_buttonValue]._name; + Common::String spellName = _spells[newSelection]._name; Common::String msg = (castingCopy & 0x80) ? Common::String::format(SPELLS_PRESS_A_KEY, msg.c_str()) : Common::String::format(SPELLS_PURCHASE, msg.c_str(), spellCost); @@ -273,6 +274,9 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int } while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE); screen._windows[25].close(); + + if (_vm->shouldQuit()) + selection = -1; if (isCasting && selection != -1) c->_currentSpell = _spells[selection]._spellIndex; @@ -479,7 +483,6 @@ int CastSpell::execute(Character *&c, int mode) { Window &w = screen._windows[10]; Mode oldMode = (Mode)mode; - int category = c->getClassCategory(); w.open(); loadButtons(); @@ -488,6 +491,7 @@ int CastSpell::execute(Character *&c, int mode) { bool redrawFlag = true; do { if (redrawFlag) { + int category = c->getClassCategory(); int spellIndex = c->_currentSpell != -1 ? c->_currentSpell : 39; spellId = SPELLS_ALLOWED[category][spellIndex]; int gemCost = SPELL_GEM_COST[spellId]; -- cgit v1.2.3 From b66bf1a838b01181c93b19e214c59c810e05955d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 19 Feb 2015 21:12:33 -0500 Subject: XEEN: Implemented stopAttack --- engines/xeen/combat.cpp | 106 ++++++++++++++++++++++++++++++++++++++++++++++-- engines/xeen/combat.h | 2 +- 2 files changed, 103 insertions(+), 5 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 7ed349906d..a9ead958a8 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -568,15 +568,113 @@ void Combat::attackMonster(int monsterId) { } -bool Combat::stopAttack(const Common::Point &diffPt) { +int Combat::stopAttack(const Common::Point &diffPt) { Map &map = *_vm->_map; + Party &party = *_vm->_party; + Direction dir = party._mazeDirection; + const Common::Point &mazePos = party._mazePosition; if (map._isOutdoors) { + if (diffPt.x > 0) { + for (int x = 1; x <= diffPt.x; ++x) { + int v = map.mazeLookup(Common::Point(mazePos.x + x, mazePos.y), 0, 8); + if (v) + return 0; + } + return (dir == DIR_EAST) ? diffPt.x + 1 : 1; + + } else if (diffPt.x < 0) { + for (int x = diffPt.x; x < 0; ++x) { + int v = map.mazeLookup(Common::Point(mazePos.x + x, mazePos.y), 4); + switch (v) { + case 0: + case 2: + case 4: + case 5: + case 8: + case 11: + case 13: + case 14: + break; + default: + return 0; + } + } + return dir == DIR_WEST ? diffPt.x * -1 + 1 : 1; + + } else if (diffPt.y <= 0) { + for (int y = diffPt.y; y < 0; ++y) { + int v = map.mazeLookup(Common::Point(mazePos.x, mazePos.y + y), 4); + switch (v) { + case 0: + case 2: + case 4: + case 5: + case 8: + case 11: + case 13: + case 14: + break; + default: + return 0; + } + } + return party._mazeDirection == DIR_SOUTH ? diffPt.y * -1 + 1 : 1; - } + } else { + for (int y = 1; y <= diffPt.y; ++y) { + int v = map.mazeLookup(Common::Point(mazePos.x, mazePos.y + y), 4); + switch (v) { + case 0: + case 2: + case 4: + case 5: + case 8: + case 11: + case 13: + case 14: + break; + default: + return 0; + } + } + return dir == DIR_NORTH ? diffPt.y + 1 : 1; + } + } else { + // Indoors + if (diffPt.x > 0) { + for (int x = 1; x <= diffPt.x; ++x) { + int v = map.mazeLookup(Common::Point(mazePos.x + x, mazePos.y), 0, 8); + if (v) + return 0; + } + return dir == DIR_EAST ? diffPt.x + 1 : 1; - // TODO - return false; + } else if (diffPt.x < 0) { + for (int x = diffPt.x; x < 0; ++x) { + int v = map.mazeLookup(Common::Point(mazePos.x + x, mazePos.y), 0, 0x800); + if (v) + return 0; + } + return dir == DIR_WEST ? diffPt.x * -1 + 1 : 1; + + } else if (diffPt.y <= 0) { + for (int y = diffPt.y; y < 0; ++y) { + int v = map.mazeLookup(Common::Point(mazePos.x, mazePos.y + y), 0, 0x8000); + if (v) + return 0; + } + return dir == DIR_SOUTH ? diffPt.y * -1 + 1 : 1; + + } else { + for (int y = 1; y <= diffPt.y; ++y) { + int v = map.mazeLookup(Common::Point(mazePos.x, mazePos.y + y), 0, 0x80); + if (v) + return 0; + } + return dir == DIR_NORTH ? diffPt.y + 1 : 1; + } + } } /** diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 5ff6beb16b..b9293233e7 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -99,7 +99,7 @@ public: void monsterOvercome(); - bool stopAttack(const Common::Point &diffPt); + int stopAttack(const Common::Point &diffPt); public: Combat(XeenEngine *vm); -- cgit v1.2.3 From caf7f376b3fd8bb1bfd3e658139b547695033dde Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 20 Feb 2015 08:47:38 -0500 Subject: XEEN: Implemented monsterAttack --- engines/xeen/combat.cpp | 184 ++++++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/combat.h | 2 + engines/xeen/map.h | 2 +- 3 files changed, 187 insertions(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index a9ead958a8..b6d1f7fe1d 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -236,6 +236,13 @@ loop: } } +/** + * Do damage to a specific character + */ +void Combat::doCharDamage(Character *c, int monsterDataIndex) { + error("TODO"); +} + void Combat::moveMonsters() { Interface &intf = *_vm->_interface; Map &map = *_vm->_map; @@ -565,7 +572,184 @@ void Combat::monsterOvercome() { } void Combat::attackMonster(int monsterId) { + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + int monRefId; + + if (_monstersAttacking) { + warning("TODO: Original used uninitialized variables if flag was set"); + return; + } + + int monsterIndex; + switch (_whosTurn - _combatParty.size()) { + case 0: + monsterIndex = _attackMonsters[0]; + intf._indoorList[156]._scale = 0; + break; + case 1: + monsterIndex = _attackMonsters[1]; + intf._indoorList[150]._scale = 0; + break; + case 2: + default: + monsterIndex = _attackMonsters[2]; + intf._indoorList[153]._scale = 0; + } + + MazeMonster &monster = map._mobData._monsters[monsterIndex]; + MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + if (monster._field7) + return; + + monster._frame = 8; + monster._fieldA = 3; + monster._field9 = 0; + intf.draw3d(true); + intf.draw3d(true); + + File f(monsterData._attackVoc); + sound.playSample(&f, 0); + bool flag = false; + + for (int attackNum = 0; attackNum < monsterData._numberOfAttacks; ++attackNum) { + int charNum = -1; + bool isHated = false; + + if (monsterData._hatesClass != -1) { + if (monsterData._hatesClass == 15) + // Monster hates all classes + goto loop; + + for (uint charIndex = 0; charIndex < _combatParty.size(); ++charIndex) { + Character &c = *_combatParty[charIndex]; + Condition cond = c.worstCondition(); + if (cond >= PARALYZED && cond <= ERADICATED) + continue; + + bool isHated = false; + switch (monsterData._hatesClass) { + case CLASS_KNIGHT: + case CLASS_PALADIN: + case CLASS_ARCHER: + case CLASS_CLERIC: + case CLASS_SORCERER: + case CLASS_ROBBER: + case CLASS_NINJA: + case CLASS_BARBARIAN: + case CLASS_DRUID: + case CLASS_RANGER: + isHated = c._class == monsterData._hatesClass; + break; + case 12: + isHated = c._race == DWARF; + break; + default: + break; + } + + if (isHated) { + charNum = charIndex; + break; + } + } + } + + if (!isHated) { + // No particularly hated foe, so decide which character to start with + switch (_combatParty.size()) { + case 1: + charNum = 0; + break; + case 2: + case 3: + case 4: + case 5: + charNum = _vm->getRandomNumber(0, _combatParty.size() - 1); + break; + case 6: + if (_vm->getRandomNumber(1, 6) == 6) + charNum = 5; + else + charNum = _vm->getRandomNumber(0, 4); + break; + } + } + + // Attacking loop + do { + if (!flag) { + Condition cond = _combatParty[charNum]->worstCondition(); + + if (cond >= PARALYZED && cond <= ERADICATED) { + Common::Array<int> ableChars; + bool skip = false; + + for (uint idx = 0; idx < _combatParty.size() && !skip; ++idx) { + switch (_combatParty[idx]->worstCondition()) { + case PARALYZED: + case UNCONSCIOUS: + if (flag) + skip = true; + break; + case DEAD: + case STONED: + case ERADICATED: + break; + default: + ableChars.push_back(idx); + break; + } + } + + if (!skip) { + if (ableChars.size() == 0) { + party._dead = true; + _vm->_mode = MODE_1; + return; + } + + charNum = ableChars[_vm->getRandomNumber(0, ableChars.size() - 1)]; + } + } + } + + // Unconditional if to get around goto initialization errors + if (true) { + Character &c = *_combatParty[charNum]; + if (monsterData._attackType != DT_PHYSICAL || c._conditions[ASLEEP]) { + doCharDamage(&c, monster._spriteId); + } else { + int v = _vm->getRandomNumber(1, 20); + if (v == 1) { + sound.playFX(6); + } else { + if (v == 20) + doCharDamage(&c, monster._spriteId); + v += monsterData._hitChance / 4 + _vm->getRandomNumber(1, + monsterData._hitChance); + + int ac = c.getArmorClass() + (!_charsBlocked[charNum] ? 10 : + c.getCurrentLevel() / 2 + 15); + if (ac > v) { + sound.playFX(6); + } else { + doCharDamage(&c, monster._spriteId); + } + } + } + + if (flag) + break; + } +loop: + flag = true; + } while (++charNum < (int)_combatParty.size()); + } + intf.drawParty(true); } int Combat::stopAttack(const Common::Point &diffPt) { diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index b9293233e7..df42a4031f 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -107,6 +107,8 @@ public: void giveCharDamage(int damage, DamageType attackType, int charIndex); + void doCharDamage(Character *c, int monsterDataIndex); + void moveMonsters(); void setupCombatParty(); diff --git a/engines/xeen/map.h b/engines/xeen/map.h index a43cef516e..05ead5b974 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -54,7 +54,7 @@ public: int _accuracy; int _speed; int _numberOfAttacks; - CharacterClass _hatesClass; + int _hatesClass; int _strikes; int _dmgPerStrike; DamageType _attackType; -- cgit v1.2.3 From ebc134a267046d78b1cef125f2a318e497bdf45f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 20 Feb 2015 20:08:39 -0500 Subject: XEEN: Implement attackMonster and breakAllItems --- engines/xeen/character.cpp | 18 +++++ engines/xeen/character.h | 2 + engines/xeen/combat.cpp | 179 +++++++++++++++++++++++++++++++++++++++++++-- engines/xeen/combat.h | 2 +- 4 files changed, 194 insertions(+), 7 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index c91b860640..04f83253d4 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -669,6 +669,24 @@ InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) { return *_itemSets[category]; } +/** + * Breaks all the items in a given character's inventory + */ +void InventoryItemsGroup::breakAllItems() { + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + if ((*_itemSets[0])[idx]._id != 34) { + (*_itemSets[0])[idx]._bonusFlags |= ITEMFLAG_BROKEN; + (*_itemSets[0])[idx]._frame = 0; + } + + (*_itemSets[1])[idx]._bonusFlags |= ITEMFLAG_BROKEN; + (*_itemSets[2])[idx]._bonusFlags |= ITEMFLAG_BROKEN; + (*_itemSets[3])[idx]._bonusFlags |= ITEMFLAG_BROKEN; + (*_itemSets[1])[idx]._frame = 0; + (*_itemSets[2])[idx]._frame = 0; + } +} + /*------------------------------------------------------------------------*/ diff --git a/engines/xeen/character.h b/engines/xeen/character.h index bf77bef315..6acd433adc 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -201,6 +201,8 @@ public: InventoryItems &accessories, InventoryItems &misc); InventoryItems &operator[](ItemCategory category); + + void breakAllItems(); }; diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index b6d1f7fe1d..514201565a 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -239,8 +239,176 @@ loop: /** * Do damage to a specific character */ -void Combat::doCharDamage(Character *c, int monsterDataIndex) { - error("TODO"); +void Combat::doCharDamage(Character &c, int charNum, int monsterDataIndex) { + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + MonsterStruct &monsterData = map._monsterData[monsterDataIndex]; + + // Attacked characters are automatically woken up + c._conditions[ASLEEP] = 0; + + // Figure out the damage amount + int damage = 0; + for (int idx = 0; idx < monsterData._strikes; ++idx) + damage += _vm->getRandomNumber(1, monsterData._dmgPerStrike); + + + int fx = 29, frame = 0; + if (monsterData._attackType) { + if (c.charSavingThrow(monsterData._attackType)) + damage /= 2; + + switch (monsterData._attackType) { + case DT_MAGICAL: + frame = 6; + fx = 27; + break; + case DT_FIRE: + damage -= party._fireResistence; + frame = 1; + fx = 22; + break; + case DT_ELECTRICAL: + damage -= party._electricityResistence; + frame = 2; + fx = 23; + break; + case DT_COLD: + damage -= party._coldResistence; + frame = 3; + fx = 24; + break; + case DT_POISON: + damage -= party._poisonResistence; + frame = 4; + fx = 26; + break; + case DT_ENERGY: + frame = 5; + fx = 25; + break; + default: + break; + } + + while (damage > 0 && c.charSavingThrow(monsterData._attackType)) + damage /= 2; + } + + sound.playFX(fx); + intf._charPowSprites.draw(screen, frame, Common::Point(CHAR_FACES_X[charNum], 150)); + screen._windows[33].update(); + + damage -= party._powerShield; + if (damage > 0 && monsterData._specialAttack && !c.charSavingThrow(DT_PHYSICAL)) { + switch (monsterData._specialAttack) { + case SA_POISON: + if (!++c._conditions[POISONED]) + c._conditions[POISONED] = -1; + sound.playFX(26); + break; + case SA_DISEASE: + if (!++c._conditions[DISEASED]) + c._conditions[DISEASED] = -1; + sound.playFX(26); + break; + case SA_INSANE: + if (!++c._conditions[INSANE]) + c._conditions[INSANE] = -1; + sound.playFX(28); + break; + case SA_SLEEP: + if (!++c._conditions[ASLEEP]) + c._conditions[ASLEEP] = -1; + sound.playFX(36); + break; + case SA_CURSEITEM: + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + if (c._weapons[idx]._id != 34) + c._weapons[idx]._bonusFlags |= ITEMFLAG_CURSED; + c._armor[idx]._bonusFlags |= ITEMFLAG_CURSED; + c._accessories[idx]._bonusFlags |= ITEMFLAG_CURSED; + c._misc[idx]._bonusFlags |= ITEMFLAG_CURSED;; + } + sound.playFX(37); + break; + case SA_DRAINSP: + c._currentSp = 0; + sound.playFX(37); + break; + case SA_CURSE: + if (!++c._conditions[CURSED]) + c._conditions[CURSED] = -1; + sound.playFX(37); + break; + case SA_PARALYZE: + if (!++c._conditions[PARALYZED]) + c._conditions[PARALYZED] = -1; + sound.playFX(37); + break; + case SA_UNCONSCIOUS: + if (!++c._conditions[UNCONSCIOUS]) + c._conditions[UNCONSCIOUS] = -1; + sound.playFX(37); + break; + case SA_CONFUSE: + if (!++c._conditions[CONFUSED]) + c._conditions[CONFUSED] = -1; + sound.playFX(28); + break; + case SA_BREAKWEAPON: + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + XeenItem &weapon = c._weapons[idx]; + if (weapon._id != 34 && weapon._id != 0 && weapon._frame != 0) { + weapon._bonusFlags |= ITEMFLAG_BROKEN; + weapon._frame = 0; + } + } + sound.playFX(37); + break; + case SA_WEAKEN: + if (!++c._conditions[WEAK]) + c._conditions[WEAK] = -1; + sound.playFX(36); + break; + case SA_ERADICATE: + if (!++c._conditions[ERADICATED]) + c._conditions[ERADICATED] = -1; + c._items.breakAllItems(); + sound.playFX(37); + + if (c._currentHp > 0) + c._currentHp = 0; + break; + case SA_AGING: + ++c._tempAge; + sound.playFX(37); + break; + case SA_DEATH: + if (!++c._conditions[DEAD]) + c._conditions[DEAD] = -1; + sound.playFX(38); + if (c._currentHp > 0) + c._currentHp = 0; + break; + case SA_STONE: + if (!++c._conditions[STONED]) + c._conditions[STONED] = -1; + sound.playFX(38); + if (c._currentHp > 0) + c._currentHp = 0; + break; + } + + c.subtractHitPoints(damage); + } + + events.ipause(2); + intf.drawParty(true); } void Combat::moveMonsters() { @@ -576,7 +744,6 @@ void Combat::attackMonster(int monsterId) { Map &map = *_vm->_map; Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; - int monRefId; if (_monstersAttacking) { warning("TODO: Original used uninitialized variables if flag was set"); @@ -720,14 +887,14 @@ void Combat::attackMonster(int monsterId) { if (true) { Character &c = *_combatParty[charNum]; if (monsterData._attackType != DT_PHYSICAL || c._conditions[ASLEEP]) { - doCharDamage(&c, monster._spriteId); + doCharDamage(c, charNum, monster._spriteId); } else { int v = _vm->getRandomNumber(1, 20); if (v == 1) { sound.playFX(6); } else { if (v == 20) - doCharDamage(&c, monster._spriteId); + doCharDamage(c, charNum, monster._spriteId); v += monsterData._hitChance / 4 + _vm->getRandomNumber(1, monsterData._hitChance); @@ -736,7 +903,7 @@ void Combat::attackMonster(int monsterId) { if (ac > v) { sound.playFX(6); } else { - doCharDamage(&c, monster._spriteId); + doCharDamage(c, charNum, monster._spriteId); } } } diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index df42a4031f..60adbca063 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -107,7 +107,7 @@ public: void giveCharDamage(int damage, DamageType attackType, int charIndex); - void doCharDamage(Character *c, int monsterDataIndex); + void doCharDamage(Character &c, int charNum, int monsterDataIndex); void moveMonsters(); -- cgit v1.2.3 From 917b143ec9e7fd9f5c9b28088c2b7f6310c16cee Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 20 Feb 2015 21:55:40 -0500 Subject: XEEN: Implement attack method --- engines/xeen/character.cpp | 1 - engines/xeen/combat.cpp | 234 ++++++++++++++++++++++++++++++++++++++-- engines/xeen/combat.h | 61 ++++++----- engines/xeen/dialogs_spells.cpp | 8 +- engines/xeen/interface_map.cpp | 2 +- engines/xeen/map.cpp | 2 +- engines/xeen/map.h | 2 +- engines/xeen/scripts.cpp | 2 +- 8 files changed, 273 insertions(+), 39 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index 04f83253d4..737c36ab30 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -1855,5 +1855,4 @@ int Character::getClassCategory() const { } } - } // End of namespace Xeen diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 514201565a..776821a5f4 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -77,6 +77,8 @@ static const int MONSTER_SHOOT_POW[7] = { 12, 14, 0, 4, 8, 10, 13 }; static const int COMBAT_SHOOTING[4] = { 1, 1, 2, 3 }; +#define monsterSavingThrow(MONINDEX) (_vm->getRandomNumber(1, 50 + MONINDEX) <= MONINDEX) + /*------------------------------------------------------------------------*/ Combat::Combat(XeenEngine *vm): _vm(vm) { @@ -91,6 +93,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm) { Common::fill(&_monsterMoved[0], &_monsterMoved[MAX_NUM_MONSTERS], false); Common::fill(&_rangeAttacking[0], &_rangeAttacking[MAX_NUM_MONSTERS], false); Common::fill(&_gmonHit[0], &_gmonHit[36], 0); + Common::fill(&_missedShot[0], &_missedShot[MAX_PARTY_COUNT], 0); _globalCombat = 0; _whosTurn = -1; _itemFlag = false; @@ -102,6 +105,9 @@ Combat::Combat(XeenEngine *vm): _vm(vm) { _whosSpeed = 0; _damageType = DT_PHYSICAL; _oldCharacter = nullptr; + _shootType = 0; + _monsterDamage = 0; + _weaponDamage = 0; } void Combat::clear() { @@ -455,7 +461,7 @@ void Combat::moveMonsters() { // Check for range attacks if (monsterData._rangeAttack && !_rangeAttacking[idx] && _attackMonsters[0] != idx && _attackMonsters[1] != idx - && _attackMonsters[2] != idx && !monster._field7) { + && _attackMonsters[2] != idx && !monster._damageType) { // Setup monster for attacking setupMonsterAttack(monster._spriteId, pt); _rangeAttacking[idx] = true; @@ -683,7 +689,7 @@ void Combat::moveMonster(int monsterId, const Common::Point &pt) { Map &map = *_vm->_map; MazeMonster &monster = map._mobData._monsters[monsterId]; - if (_monsterMap[pt.y][pt.x] < 3 && !monster._field7 && _vm->_moveMonsters) { + if (_monsterMap[pt.y][pt.x] < 3 && !monster._damageType && _vm->_moveMonsters) { ++_monsterMap[pt.y][pt.x]; --_monsterMap[monster._position.y][monster._position.x]; monster._position = pt; @@ -731,10 +737,10 @@ void Combat::monsterOvercome() { MazeMonster &monster = map._mobData._monsters[idx]; int dataIndex = monster._spriteId; - if (monster._field7 != 0 && monster._field7 != 13) { + if (monster._damageType != 0 && monster._damageType != 13) { // Do a saving throw for monster if (dataIndex <= _vm->getRandomNumber(1, dataIndex + 50)) - monster._field7 = 0; + monster._damageType = 0; } } } @@ -768,7 +774,7 @@ void Combat::attackMonster(int monsterId) { MazeMonster &monster = map._mobData._monsters[monsterIndex]; MonsterStruct &monsterData = map._monsterData[monster._spriteId]; - if (monster._field7) + if (monster._damageType) return; monster._frame = 8; @@ -1153,7 +1159,210 @@ Common::String Combat::getMonsterDescriptions() { lines[1].c_str(), lines[2].c_str()); } -void Combat::attack(Character &c, int v2) { +void Combat::attack(Character &c, int ranged) { + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + int damage = _monsterDamage; + + if (_monster2Attack == -1) + return; + + MazeMonster &monster = map._mobData._monsters[_monster2Attack]; + int monsterDataIndex = monster._spriteId; + MonsterStruct &monsterData = map._monsterData[monsterDataIndex]; + + if (ranged) { + if (_shootType != 1 || _damageType == DT_MAGIC_ARROW) { + if (!monsterData._magicResistence || monsterData._magicResistence <= + _vm->getRandomNumber(1, 100 + _oldCharacter->getCurrentLevel())) { + if (_monsterDamage != 0) { + attack2(damage, ranged); + setSpeedTable(); + } else { + switch (_damageType) { + case DT_SLEEP: + if (monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID) { + if (_vm->getRandomNumber(1, 50 + monsterDataIndex) > monsterDataIndex) + monster._damageType = DT_SLEEP; + } + break; + case DT_FINGEROFDEATH: + if ((monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID) + && !monsterSavingThrow(monsterDataIndex)) { + damage = MIN(monster._hp, 50); + attack2(damage, 2); + setSpeedTable(); + } + break; + case DT_HOLYWORD: + if (monsterData._monsterType == MONSTER_UNDEAD) { + attack2(monster._hp, 2); + setSpeedTable(); + } + break; + case DT_MASS_DISTORTION: + attack2(MAX(monster._hp / 2, 1), 2); + setSpeedTable(); + break; + case DT_UNDEAD: + if (monsterData._monsterType == MONSTER_UNDEAD) + damage = 25; + else + ranged = 2; + attack2(damage, ranged); + setSpeedTable(); + break; + case DT_BEASTMASTER: + if ((monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID) + && !monsterSavingThrow(monsterDataIndex)) { + monster._damageType = DT_BEASTMASTER; + } + break; + case DT_DRAGONSLEEP: + if (monsterData._monsterType == MONSTER_DRAGON && !monsterSavingThrow(monsterDataIndex)) + monster._damageType = DT_DRAGONSLEEP; + break; + case DT_GOLEMSTOPPER: + if (monsterData._monsterType == MONSTER_GOLEM) { + attack2(100, ranged); + setSpeedTable(); + } + break; + case DT_HYPNOTIZE: + if ((monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID) + && !monsterSavingThrow(monsterDataIndex)) { + monster._damageType = _damageType; + } + break; + case DT_INSECT_SPRAY: + if (monsterData._monsterType == MONSTER_INSECT) { + attack2(25, ranged); + setSpeedTable(); + } + break; + case DT_MAGIC_ARROW: + attack2(8, ranged); + setSpeedTable(); + break; + default: + break; + } + } + } + } else { + Common::fill(&_elemPow[0], &_elemPow[PARTY_AND_MONSTERS], 0); + damage = 0; + + for (uint charIndex = 0; charIndex < party._activeParty.size(); ++charIndex) { + Character &c = party._activeParty[charIndex]; + + if (_shooting[charIndex] && !_missedShot[charIndex]) { + if (!hitMonster(c, ranged)) { + ++_missedShot[charIndex]; + } else { + damage = _monsterDamage ? _monsterDamage : _weaponDamage; + _shooting[charIndex] = 0; + attack2(damage, ranged); + + if (map._isOutdoors) { + intf._outdoorList._attackImgs1[charIndex]._scale = 0; + intf._outdoorList._attackImgs1[charIndex]._sprites = nullptr; + intf._outdoorList._attackImgs2[charIndex]._scale = 0; + intf._outdoorList._attackImgs2[charIndex]._sprites = nullptr; + intf._outdoorList._attackImgs3[charIndex]._scale = 0; + intf._outdoorList._attackImgs3[charIndex]._sprites = nullptr; + intf._outdoorList._attackImgs4[charIndex]._scale = 0; + intf._outdoorList._attackImgs4[charIndex]._sprites = nullptr; + } else { + intf._indoorList._attackImgs1[charIndex]._scale = 0; + intf._indoorList._attackImgs1[charIndex]._sprites = nullptr; + intf._indoorList._attackImgs2[charIndex]._scale = 0; + intf._indoorList._attackImgs2[charIndex]._sprites = nullptr; + intf._indoorList._attackImgs3[charIndex]._scale = 0; + intf._indoorList._attackImgs3[charIndex]._sprites = nullptr; + intf._indoorList._attackImgs4[charIndex]._scale = 0; + intf._indoorList._attackImgs4[charIndex]._sprites = nullptr; + } + + if (_monster2Attack == -1) + return; + } + } + } + } + } else { + _damageType = DT_PHYSICAL; + int divisor = 0; + switch (c._class) { + case CLASS_BARBARIAN: + divisor = 4; + break; + case CLASS_KNIGHT: + case CLASS_NINJA: + divisor = 5; + break; + case CLASS_PALADIN: + case CLASS_ARCHER: + case CLASS_ROBBER: + case CLASS_RANGER: + divisor = 6; + break; + case CLASS_CLERIC: + case CLASS_DRUID: + divisor = 7; + break; + case CLASS_SORCERER: + divisor = 8; + break; + } + + int numberOfAttacks = c.getCurrentLevel() / divisor; + damage = 0; + + while (numberOfAttacks-- > 0) { + if (hitMonster(c, 0)) + damage += getMonsterDamage(c); + } + + for (int itemIndex = 0; itemIndex < INV_ITEMS_TOTAL; ++itemIndex) { + XeenItem &weapon = c._weapons[itemIndex]; + if (weapon._frame != 0) { + switch (weapon._bonusFlags & ITEMFLAG_BONUS_MASK) { + case 1: + if (monsterData._monsterType == MONSTER_DRAGON) + damage *= 3; + break; + case 2: + if (monsterData._monsterType == MONSTER_UNDEAD) + damage *= 3; + break; + case 3: + if (monsterData._monsterType == MONSTER_GOLEM) + damage *= 3; + break; + case 4: + if (monsterData._monsterType == MONSTER_INSECT) + damage *= 3; + break; + case 5: + if (monsterData._monsterType == MONSTER_0) + damage *= 3; + break; + case 6: + if (monsterData._monsterType == MONSTER_ANIMAL) + damage *= 3; + break; + } + } + } + + attack2(damage, ranged); + setSpeedTable(); + } +} + +void Combat::attack2(int damage, int ranged) { error("TODO"); } @@ -1213,4 +1422,17 @@ void Combat::run() { } } +bool Combat::hitMonster(Character &c, int ranged) { + error("TODO"); +} + +bool Combat::getWeaponDamage(Character &c, int ranged) { + error("TODO"); +} + +int Combat::getMonsterDamage(Character &c) { + error("TODO"); +} + + } // End of namespace Xeen diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 60adbca063..1e1ca82808 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -30,12 +30,13 @@ namespace Xeen { #define MAX_NUM_MONSTERS 107 +#define PARTY_AND_MONSTERS 11 enum DamageType { DT_PHYSICAL = 0, DT_MAGICAL = 1, DT_FIRE = 2, DT_ELECTRICAL = 3, DT_COLD = 4, DT_POISON = 5, DT_ENERGY = 6, DT_SLEEP = 7, DT_FINGEROFDEATH = 8, DT_HOLYWORD = 9, DT_MASS_DISTORTION = 10, - DT_UNDED = 11, DT_BEASTMASTER = 12, DT_DRAGONSLEEP = 13, + DT_UNDEAD = 11, DT_BEASTMASTER = 12, DT_DRAGONSLEEP = 13, DT_GOLEMSTOPPER = 14, DT_HYPNOTIZE = 15, DT_INSECT_SPRAY = 16, DT_POISON_VALLEY = 17, DT_MAGIC_ARROW = 18 }; @@ -55,6 +56,14 @@ class Character; class Combat { private: XeenEngine *_vm; + + void attack2(int damage, int ranged); + + bool hitMonster(Character &c, int ranged); + + bool getWeaponDamage(Character &c, int ranged); + + int getMonsterDamage(Character &c); public: Common::Array<Character *> _combatParty; Common::Array<bool> _charsBlocked; @@ -62,11 +71,12 @@ public: SpriteResource _powSprites; int _attackMonsters[26]; int _monster2Attack; - int _charsArray1[12]; - bool _monPow[12]; - int _monsterScale[12]; - int _elemPow[12]; - int _elemScale[12]; + int _charsArray1[PARTY_AND_MONSTERS]; + bool _monPow[PARTY_AND_MONSTERS]; + int _monsterScale[PARTY_AND_MONSTERS]; + int _elemPow[PARTY_AND_MONSTERS]; + int _elemScale[PARTY_AND_MONSTERS]; + int _missedShot[8]; Common::Array<int> _speedTable; int _shooting[8]; int _globalCombat; @@ -83,23 +93,9 @@ public: int _whosSpeed; DamageType _damageType; Character *_oldCharacter; - - void monstersAttack(); - - void setupMonsterAttack(int monsterDataIndex, const Common::Point &pt); - - bool monsterCanMove(const Common::Point &pt, int wallShift, - int v1, int v2, int monsterId); - - void moveMonster(int monsterId, const Common::Point &pt); - - void attackMonster(int monsterId); - - void endAttack(); - - void monsterOvercome(); - - int stopAttack(const Common::Point &diffPt); + int _shootType; + int _monsterDamage; + int _weaponDamage; public: Combat(XeenEngine *vm); @@ -121,7 +117,7 @@ public: Common::String getMonsterDescriptions(); - void attack(Character &c, int v2); + void attack(Character &c, int ranged); void block(); @@ -130,6 +126,23 @@ public: void giveTreasure(); void run(); + + void monstersAttack(); + + void setupMonsterAttack(int monsterDataIndex, const Common::Point &pt); + + bool monsterCanMove(const Common::Point &pt, int wallShift, + int v1, int v2, int monsterId); + + void moveMonster(int monsterId, const Common::Point &pt); + + void attackMonster(int monsterId); + + void endAttack(); + + void monsterOvercome(); + + int stopAttack(const Common::Point &diffPt); }; } // End of namespace Xeen diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 0383886c4d..ea423aac72 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -51,7 +51,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int int castingCopy = isCasting; isCasting &= 0x7f; int selection = -1; - uint topIndex = 0; + int topIndex = 0; int newSelection; screen._windows[25].open(); @@ -87,7 +87,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int Common::fill(&colors[0], &colors[10], 9); for (int idx = 0; idx < 10; ++idx) { - if ((topIndex + idx) < _spells.size()) { + if ((topIndex + idx) < (int)_spells.size()) { names[idx] = _spells[topIndex + idx]._name.c_str(); colors[idx] = _spells[topIndex + idx]._color; } @@ -256,7 +256,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int case Common::KEYCODE_PAGEDOWN: case Common::KEYCODE_KP3: - topIndex = MIN(topIndex + 10, ((_spells.size() - 1) / 10) * 10); + topIndex = MIN(topIndex + 10, (((int)_spells.size() - 1) / 10) * 10); break; case Common::KEYCODE_UP: @@ -267,7 +267,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int case Common::KEYCODE_DOWN: case Common::KEYCODE_KP2: - if (topIndex < (_spells.size() - 10)) + if (topIndex < ((int)_spells.size() - 10)) ++topIndex; break; } diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index d6d15d691f..8032369cc6 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -705,7 +705,7 @@ void InterfaceMap::animate3d() { for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) { MazeMonster &monster = map._mobData._monsters[idx]; - if (!monster._field7) { + if (!monster._damageType) { if (monster._frame < 8) { MonsterStruct &monsterData = map._monsterData[monster._spriteId]; if (!monsterData._loopAnimation) { diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 01c050a10a..10fba6d6b0 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -652,7 +652,7 @@ MazeMonster::MazeMonster() { _id = 0; _spriteId = 0; _isAttacking = false; - _field7 = 0; + _damageType = DT_PHYSICAL; _field9 = 0; _fieldA = 0; _hp = 0; diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 05ead5b974..7faf59fc04 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -245,7 +245,7 @@ struct MazeMonster { int _id; int _spriteId; bool _isAttacking; - int _field7; + int _damageType; int _field9; int _fieldA; int _hp; diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 37222a3d76..8b3888934b 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -508,7 +508,7 @@ void Scripts::cmdSpawn(Common::Array<byte> ¶ms) { monster._position.x = params[1]; monster._position.y = params[2]; monster._frame = _vm->getRandomNumber(7); - monster._field7 = 0; + monster._damageType = 0; monster._isAttacking = params[1] != 0; monster._hp = monsterData._hp; -- cgit v1.2.3 From b790e9bac1ee20482cbea6056dcf084bd85c0da5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 20 Feb 2015 23:57:45 -0500 Subject: XEEN: Implemented attack2 --- engines/xeen/character.h | 5 -- engines/xeen/combat.cpp | 225 +++++++++++++++++++++++++++++++++++++++++++++-- engines/xeen/combat.h | 17 +++- engines/xeen/items.cpp | 3 - engines/xeen/items.h | 11 --- engines/xeen/module.mk | 1 - engines/xeen/party.cpp | 7 ++ engines/xeen/party.h | 14 +++ engines/xeen/scripts.cpp | 11 ++- engines/xeen/scripts.h | 2 - engines/xeen/xeen.h | 1 - 11 files changed, 262 insertions(+), 35 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.h b/engines/xeen/character.h index 6acd433adc..372014f7fc 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -74,11 +74,6 @@ enum Condition { NO_CONDITION = 16 }; -enum ElementalCategory { - ELEM_FIRE = 0, ELEM_ELECTRICITY = 1, ELEM_COLD = 2, - ELEM_ACID_POISON = 3, ELEM_ENERGY = 4, ELEM_MAGIC = 5 -}; - enum AttributeCategory { ATTR_MIGHT = 0, ATTR_INTELLECT = 1, ATTR_PERSONALITY = 2, ATTR_SPEED = 3, ATTR_ACCURACY = 4, ATTR_LUCK = 5, ATTR_HIT_POINTS = 6, ATTR_SPELL_POINTS = 7, diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 776821a5f4..a8b5a50a4e 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -77,16 +77,27 @@ static const int MONSTER_SHOOT_POW[7] = { 12, 14, 0, 4, 8, 10, 13 }; static const int COMBAT_SHOOTING[4] = { 1, 1, 2, 3 }; -#define monsterSavingThrow(MONINDEX) (_vm->getRandomNumber(1, 50 + MONINDEX) <= MONINDEX) +static const int DAMAGE_TYPE_EFFECTS[19] = { + 3, 10, 4, 11, 1, 2, 5, 9, 5, 14, 5, 14, 10, 8, 3, 9, 2, 2, 3 +}; + +static const int POW_WEAPON_VOCS[35] = { + 0, 5, 4, 5, 5, 5, 5, 2, 4, 5, 3, 5, 4, 2, 3, 2, 2, 4, 5, 5, + 5, 5, 5, 1, 3, 2, 5, 1, 1, 1, 0, 0, 0, 2, 2 +}; + +static const int MONSTER_ITEM_RANGES[6] = { 10, 20, 50, 100, 100, 100 }; + +#define monsterSavingThrow(MONINDEX) (_vm->getRandomNumber(1, 50 + (MONINDEX)) <= (MONINDEX)) /*------------------------------------------------------------------------*/ -Combat::Combat(XeenEngine *vm): _vm(vm) { +Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.voc") { Common::fill(&_attackMonsters[0], &_attackMonsters[26], 0); Common::fill(&_charsArray1[0], &_charsArray1[12], 0); Common::fill(&_monPow[0], &_monPow[12], 0); Common::fill(&_monsterScale[0], &_monsterScale[12], 0); - Common::fill(&_elemPow[0], &_elemPow[12], 0); + Common::fill(&_elemPow[0], &_elemPow[12], ELEM_FIRE); Common::fill(&_elemScale[0], &_elemScale[12], 0); Common::fill(&_shooting[0], &_shooting[8], 0); Common::fill(&_monsterMap[0][0], &_monsterMap[32][32], 0); @@ -108,6 +119,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm) { _shootType = 0; _monsterDamage = 0; _weaponDamage = 0; + _attackWeapon = nullptr; } void Combat::clear() { @@ -1251,7 +1263,7 @@ void Combat::attack(Character &c, int ranged) { } } } else { - Common::fill(&_elemPow[0], &_elemPow[PARTY_AND_MONSTERS], 0); + Common::fill(&_elemPow[0], &_elemPow[PARTY_AND_MONSTERS], ELEM_FIRE); damage = 0; for (uint charIndex = 0; charIndex < party._activeParty.size(); ++charIndex) { @@ -1363,7 +1375,193 @@ void Combat::attack(Character &c, int ranged) { } void Combat::attack2(int damage, int ranged) { - error("TODO"); + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + bool isDarkCc = _vm->_files->_isDarkCc; + MazeMonster &monster = map._mobData._monsters[_monster2Attack]; + MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + bool monsterDied = false; + + if (!isDarkCc && damage && ranged && monster._spriteId == 89) + damage = 0; + + if (!damage) { + sound.playSample(&_missVoc, 1); + sound.playFX(6); + } else { + if (!isDarkCc && monster._spriteId == 89) + damage += 100; + if (monster._damageType == DT_SLEEP || monster._damageType == DT_DRAGONSLEEP) + monster._damageType = DT_PHYSICAL; + + if ((!ranged || !_damageType) && _attackWeapon->_id != 34) { + if (monsterData._phsyicalResistence != 0) { + if (monsterData._phsyicalResistence == 100) { + damage = 0; + } else { + // This doesn't seem to have any effect? + damage = (damage * 100) / 100; + } + } + } + + if (damage) { + _charsArray1[_monsterIndex] = 3; + _monPow[_monsterIndex] = _damageType == DT_PHYSICAL && (ranged == 3 || ranged == 0); + monster._frame = 11; + monster._fieldA = 5; + } + + int monsterResist = getMonsterResistence(ranged); + damage += monsterResist; + if (monsterResist > 0) { + _elemPow[_monsterIndex] = _attackWeapon->getElementalCategory(); + _elemScale[_monsterIndex] = getDamageScale(monsterResist); + } else if (ranged != 3) { + _elemPow[_monsterIndex] = ELEM_FIRE; + } + + if (ranged != 0 && ranged != 3) { + monster._effect2 = DAMAGE_TYPE_EFFECTS[_damageType]; + monster._effect1 = 0; + } + + if (ranged && monsterSavingThrow(monster._spriteId)) { + switch (_damageType) { + case DT_FINGEROFDEATH: + case DT_MASS_DISTORTION: + damage = 5; + break; + case DT_SLEEP: + case DT_HOLYWORD: + case DT_UNDEAD: + case DT_BEASTMASTER: + case DT_DRAGONSLEEP: + case DT_GOLEMSTOPPER: + case DT_HYPNOTIZE: + case DT_INSECT_SPRAY: + case DT_MAGIC_ARROW: + break; + default: + damage /= 2; + break; + } + } + + if (damage < 1) { + sound.playSample(&_missVoc, 1); + sound.playFX(6); + } else { + _monsterScale[_monsterIndex] = getDamageScale(damage); + intf.draw3d(true); + + sound.playSample(nullptr, 0); + File powVoc(Common::String::format("pow%d.voc", + POW_WEAPON_VOCS[_attackWeapon->_id])); + sound.playFX(60 + POW_WEAPON_VOCS[_attackWeapon->_id]); + sound.playSample(&powVoc, 1); + + if (monster._hp > damage) { + monster._hp -= damage; + } else { + monster._hp = 0; + monsterDied = true; + } + } + } + + intf.draw3d(true); + + if (monsterDied) { + if (!isDarkCc) { + if (_monster2Attack == 20 && party._mazeId == 41) + party._gameFlags[11] = true; + if (_monster2Attack == 8 && party._mazeId == 78) { + party._gameFlags[60] = true; + party._quests[23] = false; + + for (uint idx = 0; idx < party._activeParty.size(); ++idx) + party._activeParty[idx].setAward(42, true); + + if (_monster2Attack == 27 && party._mazeId == 29) + party._gameFlags[104] = true; + } + } + + giveExperience(monsterData._experience); + + if (party._mazeId != 85) { + party._treasure._gold = monsterData._gold; + party._treasure._gems = monsterData._gems; + + if (!isDarkCc && monster._spriteId == 89) { + party._treasure._weapons[0]._id = 90; + party._treasure._weapons[0]._bonusFlags = 0; + party._treasure._weapons[0]._material = 0; + party._treasure._hasItems = true; + party._questItems[8]++; + } + + int itemDrop = monsterData._itemDrop; + if (itemDrop) { + if (MONSTER_ITEM_RANGES[itemDrop] >= _vm->getRandomNumber(1, 100)) { + Character tempChar; + int category = tempChar.makeItem(itemDrop, 0, 0); + + switch (category) { + case CATEGORY_WEAPON: + for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { + if (party._treasure._weapons[idx]._id == 0) { + party._treasure._weapons[idx] = tempChar._weapons[0]; + party._treasure._hasItems = 1; + break; + } + } + break; + case CATEGORY_ARMOR: + for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { + if (party._treasure._armor[idx]._id == 0) { + party._treasure._armor[idx] = tempChar._armor[0]; + party._treasure._hasItems = 1; + break; + } + } + break; + case CATEGORY_ACCESSORY: + for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { + if (party._treasure._accessories[idx]._id == 0) { + party._treasure._accessories[idx] = tempChar._accessories[0]; + party._treasure._hasItems = 1; + break; + } + } + break; + case CATEGORY_MISC: + for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { + if (party._treasure._accessories[idx]._id == 0) { + party._treasure._accessories[idx] = tempChar._accessories[0]; + party._treasure._hasItems = 1; + break; + } + } + break; + } + } + } + } + + monster._position = Common::Point(0x80, 0x80); + _charsArray1[_monsterIndex] = 0; + _monster2Attack = -1; + intf.draw3d(true); + + if (_attackMonsters[0] != -1) { + _monster2Attack = _attackMonsters[0]; + _monsterIndex = 0; + } + } } /** @@ -1434,5 +1632,22 @@ int Combat::getMonsterDamage(Character &c) { error("TODO"); } +int Combat::getDamageScale(int v) { + if (v < 10) + return 5; + else if (v < 100) + return 0; + else + return 0x8000; +} + +int Combat::getMonsterResistence(int ranged) { + error("TODO"); +} + +void Combat::giveExperience(int experience) { + error("TODO"); +} + } // End of namespace Xeen diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 1e1ca82808..75614ccdf7 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -25,6 +25,7 @@ #include "common/scummsys.h" #include "common/rect.h" +#include "xeen/files.h" #include "xeen/sprites.h" namespace Xeen { @@ -50,8 +51,14 @@ enum SpecialAttack { SA_ERADICATE = 19, SA_AGING = 20, SA_DEATH = 21, SA_STONE = 22 }; +enum ElementalCategory { + ELEM_FIRE = 0, ELEM_ELECTRICITY = 1, ELEM_COLD = 2, + ELEM_ACID_POISON = 3, ELEM_ENERGY = 4, ELEM_MAGIC = 5 +}; + class XeenEngine; class Character; +class XeenItem; class Combat { private: @@ -64,6 +71,12 @@ private: bool getWeaponDamage(Character &c, int ranged); int getMonsterDamage(Character &c); + + int getDamageScale(int v); + + int getMonsterResistence(int ranged); + + void giveExperience(int experience); public: Common::Array<Character *> _combatParty; Common::Array<bool> _charsBlocked; @@ -74,7 +87,7 @@ public: int _charsArray1[PARTY_AND_MONSTERS]; bool _monPow[PARTY_AND_MONSTERS]; int _monsterScale[PARTY_AND_MONSTERS]; - int _elemPow[PARTY_AND_MONSTERS]; + ElementalCategory _elemPow[PARTY_AND_MONSTERS]; int _elemScale[PARTY_AND_MONSTERS]; int _missedShot[8]; Common::Array<int> _speedTable; @@ -96,6 +109,8 @@ public: int _shootType; int _monsterDamage; int _weaponDamage; + XeenItem *_attackWeapon; + File _missVoc, _pow1Voc; public: Combat(XeenEngine *vm); diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp index b9b531db7b..e8c0249803 100644 --- a/engines/xeen/items.cpp +++ b/engines/xeen/items.cpp @@ -25,8 +25,5 @@ namespace Xeen { -Treasure::Treasure() { - _hasItems = false; -} } // End of namespace Xeen diff --git a/engines/xeen/items.h b/engines/xeen/items.h index 1e208615f8..bfbd9e4481 100644 --- a/engines/xeen/items.h +++ b/engines/xeen/items.h @@ -27,18 +27,7 @@ namespace Xeen { -#define TOTAL_ITEMS 10 -class Treasure { -public: - XeenItem _misc[TOTAL_ITEMS]; - XeenItem _accessories[TOTAL_ITEMS]; - XeenItem _armor[TOTAL_ITEMS]; - XeenItem _weapons[TOTAL_ITEMS]; - bool _hasItems; -public: - Treasure(); -}; } // End of namespace Xeen diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index a17311c6af..1fe29c6a8e 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -32,7 +32,6 @@ MODULE_OBJS := \ font.o \ interface.o \ interface_map.o \ - items.o \ map.o \ party.o \ resources.o \ diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 993f156204..ab8abd7f92 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -57,6 +57,13 @@ void Roster::synchronize(Common::Serializer &s) { /*------------------------------------------------------------------------*/ +Treasure::Treasure() { + _hasItems = false; + _gold = _gems = 0; +} + +/*------------------------------------------------------------------------*/ + XeenEngine *Party::_vm; Party::Party(XeenEngine *vm) { diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 5d98c55b82..841fcd393a 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -48,6 +48,7 @@ enum Difficulty { ADVENTURER = 0, WARRIOR = 1 }; #define TOTAL_STATS 7 #define TOTAL_QUEST_ITEMS 85 #define TOTAL_QUEST_FLAGS 56 +#define MAX_TREASURE_ITEMS 10 class Roster: public Common::Array<Character> { public: @@ -58,6 +59,18 @@ public: void synchronize(Common::Serializer &s); }; +class Treasure { +public: + XeenItem _misc[MAX_TREASURE_ITEMS]; + XeenItem _accessories[MAX_TREASURE_ITEMS]; + XeenItem _armor[MAX_TREASURE_ITEMS]; + XeenItem _weapons[MAX_TREASURE_ITEMS]; + bool _hasItems; + int _gems, _gold; +public: + Treasure(); +}; + class Party { friend class Character; friend class InventoryItems; @@ -124,6 +137,7 @@ public: int _fallDamage; DamageType _damageType; bool _dead; + Treasure _treasure; public: Party(XeenEngine *vm); diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 8b3888934b..7aab04c4c4 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -92,8 +92,6 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) { _whoWill = 0; _itemType = 0; _treasureItems = 0; - _treasureGold = 0; - _treasureGems = 0; _lineNum = 0; _charIndex = 0; _v2 = 0; @@ -125,7 +123,7 @@ int Scripts::checkEvents() { Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0); //int items = _treasureItems; - if (_treasureGold & _treasureItems) { + if (party._treasure._gold & party._treasure._gems) { // TODO } else { // TODO @@ -591,6 +589,7 @@ void Scripts::cmdGiveExtended(Common::Array<byte> ¶ms) { void Scripts::cmdConfirmWord(Common::Array<byte> ¶ms) { Map &map = *_vm->_map; + Party &party = *_vm->_party; Common::String msg1 = params[2] ? map._events._text[params[2]] : _vm->_interface->_interfaceText; Common::String msg2; @@ -621,13 +620,13 @@ void Scripts::cmdConfirmWord(Common::Array<byte> ¶ms) { doWorldEnd(); } else { if (result == 59 && !_vm->_files->_isDarkCc) { - for (int idx = 0; idx < TOTAL_ITEMS; ++idx) { - XeenItem &item = _vm->_treasure._weapons[idx]; + for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { + XeenItem &item = party._treasure._weapons[idx]; if (!item._id) { item._id = 34; item._material = 0; item._bonusFlags = 0; - _vm->_treasure._hasItems = true; + party._treasure._hasItems = true; cmdExit(params); return; diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index cc32a9667f..1db672bd18 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -141,8 +141,6 @@ private: XeenEngine *_vm; int _charFX[6]; int _treasureItems; - int _treasureGold; - int _treasureGems; int _lineNum; int _charIndex; int _mirrorId; diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index d0a72f5868..76cb1c1159 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -149,7 +149,6 @@ public: SoundManager *_sound; Spells *_spells; Town *_town; - Treasure _treasure; Mode _mode; GameEvent _gameEvent; Common::SeekableReadStream *_eventData; -- cgit v1.2.3 From c5a98b0093330589dc269fe337a60cf0e1508785 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Feb 2015 10:43:27 -0500 Subject: XEEN: Implement more combat methods --- engines/xeen/combat.cpp | 243 +++++++++++++++++++++++++++++++++++++-------- engines/xeen/combat.h | 19 ++-- engines/xeen/interface.cpp | 4 +- engines/xeen/party.cpp | 28 ++++++ engines/xeen/party.h | 2 + 5 files changed, 248 insertions(+), 48 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index a8b5a50a4e..4b9ddd6323 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -119,7 +119,10 @@ Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.vo _shootType = 0; _monsterDamage = 0; _weaponDamage = 0; + _weaponDie = _weaponDice = 0; _attackWeapon = nullptr; + _attackWeaponId = 0; + _hitChanceBonus = 0; } void Combat::clear() { @@ -1171,7 +1174,7 @@ Common::String Combat::getMonsterDescriptions() { lines[1].c_str(), lines[2].c_str()); } -void Combat::attack(Character &c, int ranged) { +void Combat::attack(Character &c, RangeType rangeType) { Interface &intf = *_vm->_interface; Map &map = *_vm->_map; Party &party = *_vm->_party; @@ -1184,12 +1187,12 @@ void Combat::attack(Character &c, int ranged) { int monsterDataIndex = monster._spriteId; MonsterStruct &monsterData = map._monsterData[monsterDataIndex]; - if (ranged) { + if (rangeType) { if (_shootType != 1 || _damageType == DT_MAGIC_ARROW) { if (!monsterData._magicResistence || monsterData._magicResistence <= _vm->getRandomNumber(1, 100 + _oldCharacter->getCurrentLevel())) { if (_monsterDamage != 0) { - attack2(damage, ranged); + attack2(damage, rangeType); setSpeedTable(); } else { switch (_damageType) { @@ -1203,26 +1206,26 @@ void Combat::attack(Character &c, int ranged) { if ((monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID) && !monsterSavingThrow(monsterDataIndex)) { damage = MIN(monster._hp, 50); - attack2(damage, 2); + attack2(damage, RT_2); setSpeedTable(); } break; case DT_HOLYWORD: if (monsterData._monsterType == MONSTER_UNDEAD) { - attack2(monster._hp, 2); + attack2(monster._hp, RT_2); setSpeedTable(); } break; case DT_MASS_DISTORTION: - attack2(MAX(monster._hp / 2, 1), 2); + attack2(MAX(monster._hp / 2, 1), RT_2); setSpeedTable(); break; case DT_UNDEAD: if (monsterData._monsterType == MONSTER_UNDEAD) damage = 25; else - ranged = 2; - attack2(damage, ranged); + rangeType = RT_2; + attack2(damage, rangeType); setSpeedTable(); break; case DT_BEASTMASTER: @@ -1237,7 +1240,7 @@ void Combat::attack(Character &c, int ranged) { break; case DT_GOLEMSTOPPER: if (monsterData._monsterType == MONSTER_GOLEM) { - attack2(100, ranged); + attack2(100, rangeType); setSpeedTable(); } break; @@ -1249,12 +1252,12 @@ void Combat::attack(Character &c, int ranged) { break; case DT_INSECT_SPRAY: if (monsterData._monsterType == MONSTER_INSECT) { - attack2(25, ranged); + attack2(25, rangeType); setSpeedTable(); } break; case DT_MAGIC_ARROW: - attack2(8, ranged); + attack2(8, rangeType); setSpeedTable(); break; default: @@ -1270,12 +1273,12 @@ void Combat::attack(Character &c, int ranged) { Character &c = party._activeParty[charIndex]; if (_shooting[charIndex] && !_missedShot[charIndex]) { - if (!hitMonster(c, ranged)) { + if (!hitMonster(c, rangeType)) { ++_missedShot[charIndex]; } else { damage = _monsterDamage ? _monsterDamage : _weaponDamage; _shooting[charIndex] = 0; - attack2(damage, ranged); + attack2(damage, rangeType); if (map._isOutdoors) { intf._outdoorList._attackImgs1[charIndex]._scale = 0; @@ -1333,7 +1336,7 @@ void Combat::attack(Character &c, int ranged) { damage = 0; while (numberOfAttacks-- > 0) { - if (hitMonster(c, 0)) + if (hitMonster(c, RT_0)) damage += getMonsterDamage(c); } @@ -1369,12 +1372,12 @@ void Combat::attack(Character &c, int ranged) { } } - attack2(damage, ranged); + attack2(damage, rangeType); setSpeedTable(); } } -void Combat::attack2(int damage, int ranged) { +void Combat::attack2(int damage, RangeType rangeType) { Interface &intf = *_vm->_interface; Map &map = *_vm->_map; Party &party = *_vm->_party; @@ -1384,7 +1387,7 @@ void Combat::attack2(int damage, int ranged) { MonsterStruct &monsterData = map._monsterData[monster._spriteId]; bool monsterDied = false; - if (!isDarkCc && damage && ranged && monster._spriteId == 89) + if (!isDarkCc && damage && rangeType && monster._spriteId == 89) damage = 0; if (!damage) { @@ -1396,7 +1399,7 @@ void Combat::attack2(int damage, int ranged) { if (monster._damageType == DT_SLEEP || monster._damageType == DT_DRAGONSLEEP) monster._damageType = DT_PHYSICAL; - if ((!ranged || !_damageType) && _attackWeapon->_id != 34) { + if ((!rangeType || !_damageType) && _attackWeaponId != 34) { if (monsterData._phsyicalResistence != 0) { if (monsterData._phsyicalResistence == 100) { damage = 0; @@ -1409,26 +1412,26 @@ void Combat::attack2(int damage, int ranged) { if (damage) { _charsArray1[_monsterIndex] = 3; - _monPow[_monsterIndex] = _damageType == DT_PHYSICAL && (ranged == 3 || ranged == 0); + _monPow[_monsterIndex] = _damageType == DT_PHYSICAL && (rangeType == 3 || rangeType == 0); monster._frame = 11; monster._fieldA = 5; } - int monsterResist = getMonsterResistence(ranged); + int monsterResist = getMonsterResistence(rangeType); damage += monsterResist; if (monsterResist > 0) { _elemPow[_monsterIndex] = _attackWeapon->getElementalCategory(); _elemScale[_monsterIndex] = getDamageScale(monsterResist); - } else if (ranged != 3) { + } else if (rangeType != 3) { _elemPow[_monsterIndex] = ELEM_FIRE; } - if (ranged != 0 && ranged != 3) { + if (rangeType != 0 && rangeType != 3) { monster._effect2 = DAMAGE_TYPE_EFFECTS[_damageType]; monster._effect1 = 0; } - if (ranged && monsterSavingThrow(monster._spriteId)) { + if (rangeType && monsterSavingThrow(monster._spriteId)) { switch (_damageType) { case DT_FINGEROFDEATH: case DT_MASS_DISTORTION: @@ -1459,8 +1462,8 @@ void Combat::attack2(int damage, int ranged) { sound.playSample(nullptr, 0); File powVoc(Common::String::format("pow%d.voc", - POW_WEAPON_VOCS[_attackWeapon->_id])); - sound.playFX(60 + POW_WEAPON_VOCS[_attackWeapon->_id]); + POW_WEAPON_VOCS[_attackWeaponId])); + sound.playFX(60 + POW_WEAPON_VOCS[_attackWeaponId]); sound.playSample(&powVoc, 1); if (monster._hp > damage) { @@ -1580,7 +1583,7 @@ void Combat::quickFight() { switch (c->_quickOption) { case QUICK_ATTACK: - attack(*c, 0); + attack(*c, RT_0); break; case QUICK_SPELL: if (c->_currentSpell != -1) { @@ -1598,10 +1601,6 @@ void Combat::quickFight() { } } -void Combat::giveTreasure() { - error("TODO: giveTreasure"); -} - /** * Current selected character is trying to run away */ @@ -1620,16 +1619,98 @@ void Combat::run() { } } -bool Combat::hitMonster(Character &c, int ranged) { - error("TODO"); +bool Combat::hitMonster(Character &c, RangeType rangeType) { + Map &map = *_vm->_map; + getWeaponDamage(c, rangeType); + int chance = c.statBonus(c.getStat(ACCURACY)) + _hitChanceBonus; + int divisor; + + switch (c._class) { + case CLASS_KNIGHT: + case CLASS_BARBARIAN: + divisor = 1; + break; + case CLASS_PALADIN : + case CLASS_ARCHER: + case CLASS_ROBBER: + case CLASS_NINJA: + case CLASS_RANGER: + divisor = 2; + break; + case CLASS_CLERIC: + case CLASS_DRUID: + divisor = 3; + break; + case CLASS_SORCERER: + divisor = 4; + break; + } + + chance += c.getCurrentLevel() / divisor; + chance -= c._conditions[CURSED]; + + // Add on a random amount + int v; + do { + v = _vm->getRandomNumber(1, 20); + chance += v; + } while (v == 20); + + assert(_monster2Attack != -1); + MazeMonster &monster = map._mobData._monsters[_monster2Attack]; + MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + + if (monster._damageType != DT_PHYSICAL) + chance += 20; + + return chance >= (monsterData._accuracy + 10); } -bool Combat::getWeaponDamage(Character &c, int ranged) { - error("TODO"); +void Combat::getWeaponDamage(Character &c, RangeType rangeType) { + Party &party = *_vm->_party; + _attackWeapon = nullptr; + _weaponDie = _weaponDice = 0; + _weaponDamage = 0; + _hitChanceBonus = 0; + + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + bool flag; + if (rangeType) { + flag = c._weapons[idx]._frame == 4; + } else { + flag = c._weapons[idx]._frame == 1 || c._weapons[idx]._frame == 13; + } + + if (flag) { + if (!(c._weapons[idx]._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED))) { + _attackWeapon = &c._weapons[idx]; + + if (c._weapons[idx]._material >= 37 && c._weapons[idx]._material < 59) { + _hitChanceBonus = METAL_DAMAGE_PERCENT[c._weapons[idx]._material - 37]; + _weaponDamage = METAL_DAMAGE[c._weapons[idx]._material - 37]; + } + } + + _hitChanceBonus += party._heroism; + _attackWeaponId = c._weapons[idx]._id; + _weaponDice = WEAPON_DAMAGE_BASE[_attackWeaponId]; + _weaponDie = WEAPON_DAMAGE_MULTIPLIER[_attackWeaponId]; + + for (int diceIdx = 0; diceIdx < _weaponDice; ++diceIdx) + _weaponDamage += _vm->getRandomNumber(1, _weaponDie); + } + } + + if (_weaponDamage < 1) + _weaponDamage = 0; + if (!party._difficulty) { + _hitChanceBonus += 5; + _weaponDamage *= 3; + } } int Combat::getMonsterDamage(Character &c) { - error("TODO"); + return (c.statBonus(c.getStat(MIGHT)) + _weaponDamage) < 1; } int Combat::getDamageScale(int v) { @@ -1641,13 +1722,97 @@ int Combat::getDamageScale(int v) { return 0x8000; } -int Combat::getMonsterResistence(int ranged) { - error("TODO"); +int Combat::getMonsterResistence(RangeType rangeType) { + Map &map = *_vm->_map; + assert(_monster2Attack != -1); + MazeMonster &monster = map._mobData._monsters[_monster2Attack]; + MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + int resistence = 0, damage = 0; + + if (rangeType != RT_0 && rangeType != RT_3) { + switch (_damageType) { + case DT_PHYSICAL: + resistence = monsterData._phsyicalResistence; + break; + case DT_MAGICAL: + resistence = monsterData._magicResistence; + break; + case DT_FIRE: + resistence = monsterData._fireResistence; + break; + case DT_ELECTRICAL: + resistence = monsterData._electricityResistence; + break; + case DT_COLD: + resistence = monsterData._coldResistence; + break; + case DT_POISON: + resistence = monsterData._poisonResistence; + break; + case DT_ENERGY: + resistence = monsterData._energyResistence; + break; + default: + break; + } + } else { + int material = !_attackWeapon ? 0 : _attackWeapon->_material; + damage = ELEMENTAL_DAMAGE[material]; + + if (material != 0) { + if (material < 9) + resistence = monsterData._fireResistence; + else if (material < 16) + resistence = monsterData._electricityResistence; + else if (material < 21) + resistence = monsterData._coldResistence; + else if (material < 26) + resistence = monsterData._poisonResistence; + else if (material < 34) + resistence = monsterData._energyResistence; + else + resistence = monsterData._magicResistence; + } + } + + if (resistence != 0) { + if (resistence == 100) + return 0; + else + return ((100 - resistence) * damage) / 100; + } + + return damage; } +/** + * Distribute experience between active party members + */ void Combat::giveExperience(int experience) { - error("TODO"); -} + Party &party = *_vm->_party; + bool inCombat = _vm->_mode == MODE_COMBAT; + int count = 0; + // Two loops: first to figure out how many active characters there are, + // and the second to distribute the experience between them + for (int loopNum = 0; loopNum < 2; ++loopNum) { + for (uint charIndex = 0; charIndex < (inCombat ? _combatParty.size() : + party._activeParty.size()); ++charIndex) { + Character &c = inCombat ? *_combatParty[charIndex] : party._activeParty[charIndex]; + Condition condition = c.worstCondition(); + + if (condition != DEAD && condition != STONED && condition != ERADICATED) { + if (loopNum == 0) { + ++count; + } else { + int exp = experience / count; + if (c._level._permanent < 15) + exp /= 2; + c._experience += exp; + } + } + } + } +} } // End of namespace Xeen diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 75614ccdf7..466152a70e 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -56,6 +56,10 @@ enum ElementalCategory { ELEM_ACID_POISON = 3, ELEM_ENERGY = 4, ELEM_MAGIC = 5 }; +enum RangeType { + RT_0 = 0, RT_1 = 1, RT_2 = 2, RT_3 = 3 +}; + class XeenEngine; class Character; class XeenItem; @@ -64,17 +68,17 @@ class Combat { private: XeenEngine *_vm; - void attack2(int damage, int ranged); + void attack2(int damage, RangeType rangeType); - bool hitMonster(Character &c, int ranged); + bool hitMonster(Character &c, RangeType rangeType); - bool getWeaponDamage(Character &c, int ranged); + void getWeaponDamage(Character &c, RangeType rangeType); int getMonsterDamage(Character &c); int getDamageScale(int v); - int getMonsterResistence(int ranged); + int getMonsterResistence(RangeType rangeType); void giveExperience(int experience); public: @@ -109,8 +113,11 @@ public: int _shootType; int _monsterDamage; int _weaponDamage; + int _weaponDie, _weaponDice; XeenItem *_attackWeapon; + int _attackWeaponId; File _missVoc, _pow1Voc; + int _hitChanceBonus; public: Combat(XeenEngine *vm); @@ -132,14 +139,12 @@ public: Common::String getMonsterDescriptions(); - void attack(Character &c, int ranged); + void attack(Character &c, RangeType rangeType); void block(); void quickFight(); - void giveTreasure(); - void run(); void monstersAttack(); diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 04206581ec..1b3ee4f32c 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -1957,7 +1957,7 @@ void Interface::doCombat() { case Common::KEYCODE_a: // Attack - combat.attack(*combat._combatParty[combat._whosTurn], 0); + combat.attack(*combat._combatParty[combat._whosTurn], RT_0); nextChar(); break; @@ -2113,7 +2113,7 @@ void Interface::doCombat() { _vm->_mode = MODE_COMBAT; draw3d(true); - combat.giveTreasure(); + party.giveTreasure(); _vm->_mode = MODE_1; party._stepped = true; unhighlightChar(); diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index ab8abd7f92..aede42464b 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -559,4 +559,32 @@ void Party::moveToRunLocation() { _mazePosition = _vm->_map->mazeData()._runPosition; } +/** + * Give treasure to the party + */ +void Party::giveTreasure() { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + SoundManager &sound = *_vm->_sound; + + if (!_treasure._gold && !_treasure._gems) + return; + + bool monstersPresent = false; + for (int idx = 0; idx < 26 && !monstersPresent; ++idx) + monstersPresent = combat._attackMonsters[idx] != -1; + + if (_vm->_mode != MODE_9 && monstersPresent) + return; + + Common::fill(&combat._shooting[0], &combat._shooting[MAX_PARTY_COUNT], 0); + intf._charsShooting = false; + intf.draw3d(true); + + if (_treasure._gold || _treasure._gems) + sound.playFX(54); + + error("TODO"); +} + } // End of namespace Xeen diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 841fcd393a..483476cb9c 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -166,6 +166,8 @@ public: void checkPartyDead(); void moveToRunLocation(); + + void giveTreasure(); }; } // End of namespace Xeen -- cgit v1.2.3 From f49b1f9b4377af9693c5b1c1fdea162425c0c2b6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Feb 2015 14:34:49 -0500 Subject: XEEN: Implemented giveTreasure --- engines/xeen/character.cpp | 8 +++ engines/xeen/character.h | 5 +- engines/xeen/party.cpp | 150 ++++++++++++++++++++++++++++++++++++++++++++- engines/xeen/party.h | 5 ++ engines/xeen/resources.cpp | 27 ++++++++ engines/xeen/resources.h | 12 ++++ 6 files changed, 205 insertions(+), 2 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index 737c36ab30..e005a35f13 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -228,6 +228,14 @@ void InventoryItems::enchantItem(int itemIndex, int amount) { ErrorScroll::show(vm, Common::String::format(NOT_ENCHANTABLE, SPELL_FAILED)); } +/** + * Return if the given inventory items list is full + */ +bool InventoryItems::isFull() const { + return operator[](size() - 1)._id != 0; +} + + /*------------------------------------------------------------------------*/ /** diff --git a/engines/xeen/character.h b/engines/xeen/character.h index 372014f7fc..9e858da7fa 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -39,7 +39,8 @@ enum BonusFlags { }; enum ItemCategory { - CATEGORY_WEAPON = 0, CATEGORY_ARMOR = 1, CATEGORY_ACCESSORY = 2, CATEGORY_MISC = 3 + CATEGORY_WEAPON = 0, CATEGORY_ARMOR = 1, CATEGORY_ACCESSORY = 2, CATEGORY_MISC = 3, + NUM_ITEM_CATEGORIES = 4 }; enum Sex { MALE = 0, FEMALE = 1, YES_PLEASE = 2 }; @@ -140,6 +141,8 @@ public: void sort(); virtual void enchantItem(int itemIndex, int amount); + + bool isFull() const; }; class WeaponItems: public InventoryItems { diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index aede42464b..268dfcce15 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -60,6 +60,11 @@ void Roster::synchronize(Common::Serializer &s) { Treasure::Treasure() { _hasItems = false; _gold = _gems = 0; + + _categories[0] = &_weapons[0]; + _categories[1] = &_armor[0]; + _categories[2] = &_accessories[0]; + _categories[3] = &_misc[0]; } /*------------------------------------------------------------------------*/ @@ -564,8 +569,12 @@ void Party::moveToRunLocation() { */ void Party::giveTreasure() { Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; + Screen &screen = *_vm->_screen; + Scripts &scripts = *_vm->_scripts; SoundManager &sound = *_vm->_sound; + Window &w = screen._windows[10]; if (!_treasure._gold && !_treasure._gems) return; @@ -584,7 +593,146 @@ void Party::giveTreasure() { if (_treasure._gold || _treasure._gems) sound.playFX(54); - error("TODO"); + events.clearEvents(); + w.close(); + w.open(); + w.writeString(Common::String::format(PARTY_FOUND, _treasure._gold, _treasure._gems)); + w.update(); + + if (_vm->_mode != MODE_COMBAT) + _vm->_mode = MODE_7; + + if (arePacksFull()) + ErrorScroll::show(_vm, BACKPACKS_FULL_PRESS_KEY, WT_NONFREEZED_WAIT); + + for (int categoryNum = 0; categoryNum < NUM_ITEM_CATEGORIES; ++categoryNum) { + for (int itemNum = 0; itemNum < MAX_TREASURE_ITEMS; ++itemNum) { + if (arePacksFull()) { + if (_treasure._weapons[itemNum]._id == 34) { + // Important item, so clear a slot for it + _activeParty[0]._weapons[INV_ITEMS_TOTAL - 1].clear(); + } else { + // Otherwise, clear all the remaining treasure items, + // since all the party's packs are full + for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { + _treasure._weapons[idx].clear(); + _treasure._armor[idx].clear(); + _treasure._accessories[idx].clear(); + _treasure._armor[idx].clear(); + } + } + } + + // If there's no treasure item to be distributed, skip to next slot + if (!_treasure._categories[categoryNum][itemNum]._id) + continue; + + int charIndex = scripts._whoWill - 1; + if (charIndex >= 0 && charIndex < (int)_activeParty.size()) { + // Check the designated character first + Character &c = _activeParty[charIndex]; + if (!c._items[(ItemCategory)categoryNum].isFull() && !c.isDisabledOrDead()) { + giveTreasureToCharacter(c, (ItemCategory)categoryNum, itemNum); + continue; + } + + // Fall back on checking the entire conscious party + for (charIndex = 0; charIndex < (int)_activeParty.size(); ++charIndex) { + Character &c = _activeParty[charIndex]; + if (!c._items[(ItemCategory)categoryNum].isFull() && !c.isDisabledOrDead()) { + giveTreasureToCharacter(c, (ItemCategory)categoryNum, itemNum); + break; + } + } + if (charIndex != (int)_activeParty.size()) + continue; + } + + // At this point, find an empty pack for any character, irrespective + // of whether the character is conscious or not + for (charIndex = 0; charIndex < (int)_activeParty.size(); ++charIndex) { + Character &c = _activeParty[charIndex]; + if (!c._items[(ItemCategory)categoryNum].isFull() && !c.isDisabledOrDead()) { + giveTreasureToCharacter(c, (ItemCategory)categoryNum, itemNum); + continue; + } + } + } + } + + w.writeString(HIT_A_KEY); + w.update(); + + do { + events.updateGameCounter(); + intf.draw3d(true); + + while (!events.isKeyMousePressed() && events.timeElapsed() < 1) + events.pollEventsAndWait(); + } while (!_vm->shouldQuit() && events.timeElapsed() == 1); + + if (_vm->_mode != MODE_COMBAT) + _vm->_mode = MODE_1; + + w.close(); + _gold += _treasure._gold; + _gems += _treasure._gems; + _treasure._gold = 0; + _treasure._gems = 0; + + _treasure._hasItems = false; + for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { + _treasure._weapons[idx].clear(); + _treasure._armor[idx].clear(); + _treasure._accessories[idx].clear(); + _treasure._armor[idx].clear(); + } + + scripts._v2 = 1; +} + +/** + * Returns true if all the packs for all the characters are full + */ +bool Party::arePacksFull() const { + uint total = 0; + for (uint idx = 0; idx < _activeParty.size(); ++idx) { + const Character &c = _activeParty[idx]; + total += (c._weapons[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0) + + (c._armor[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0) + + (c._accessories[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0) + + (c._misc[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0); + } + + return total == (_activeParty.size() * NUM_ITEM_CATEGORIES); +} + +/** + * Give a treasure item to the given character's inventory + */ +void Party::giveTreasureToCharacter(Character &c, ItemCategory category, int itemIndex) { + EventsManager &events = *_vm->_events; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + Window &w = screen._windows[10]; + XeenItem &treasureItem = _treasure._categories[category][itemIndex]; + sound.playFX(20); + + if (treasureItem._id < 82) { + // Copy item into the character's inventory + c._items[category][INV_ITEMS_TOTAL - 1] = treasureItem; + c._items[category].sort(); + } + + w.writeString(GIVE_TREASURE_FORMATTING); + w.update(); + events.ipause(5); + + w.writeString(Common::String::format(X_FOUND_Y, c._name.c_str(), + ITEM_NAMES[category][treasureItem._id])); + w.update(); + + events.ipause(5); } } // End of namespace Xeen diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 483476cb9c..b5e31f9405 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -65,6 +65,7 @@ public: XeenItem _accessories[MAX_TREASURE_ITEMS]; XeenItem _armor[MAX_TREASURE_ITEMS]; XeenItem _weapons[MAX_TREASURE_ITEMS]; + XeenItem *_categories[4]; bool _hasItems; int _gems, _gold; public: @@ -76,6 +77,8 @@ class Party { friend class InventoryItems; private: static XeenEngine *_vm; + + void giveTreasureToCharacter(Character &c, ItemCategory category, int itemIndex); public: // Dynamic data that's saved Direction _mazeDirection; @@ -168,6 +171,8 @@ public: void moveToRunLocation(); void giveTreasure(); + + bool arePacksFull() const; }; } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index da57a8085b..bcf408d893 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1097,6 +1097,7 @@ const char *const BONUS_NAMES[7] = { "", "Dragon Slayer", "Undead Eater", "Golem Smasher", "Bug Zapper", "Monster Masher", "Beast Bopper" }; + const char *const WEAPON_NAMES[35] = { nullptr, "long sword ", "short sword ", "broad sword ", "scimitar ", "cutlass ", "sabre ", "club ", "hand axe ", "katana ", "nunchakas ", @@ -1124,6 +1125,10 @@ const char *const MISC_NAMES[22] = { "bogus", "bogus", "bogus", "bogus" }; +const char *const *ITEM_NAMES[4] = { + &WEAPON_NAMES[0], &ARMOR_NAMES[0], &ACCESSORY_NAMES[0], &MISC_NAMES[0] +}; + const char *const ELEMENTAL_NAMES[6] = { "Fire", "Elec", "Cold", "Acid/Poison", "Energy", "Magic" }; @@ -1501,4 +1506,26 @@ const char *const CAST_SPELL_DETAILS = "\v082Cost\x3r\t000%u/%u\x3l\n" "Cur SP\x3r\t000%u\x1"; +const char *const PARTY_FOUND = + "\x3""cThe Party Found:\n" + "\n" + "\x3r\t000%lu Gold\n" + "%lu Gems"; + +const char *const BACKPACKS_FULL_PRESS_KEY = + "\v007\f12Warning! BackPacks Full!\fd\n" + "Press a Key"; + +const char *const HIT_A_KEY = "\x3l\v120\t000\x4""077\x3""c\f37Hit a key\f'd"; + +const char *const GIVE_TREASURE_FORMATTING = + "\x3l\v060\t000\x4""077\n" + "\x4""077\n" + "\x4""077\n" + "\x4""077\n" + "\x4""077\n" + "\x4""077"; + +const char *const X_FOUND_Y = "\v060\t000\x03c%s found: %s"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index c61784475c..c98db7f0f9 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -384,6 +384,8 @@ extern const char *const WEAPON_NAMES[35]; extern const char *const ARMOR_NAMES[14]; extern const char *const ACCESSORY_NAMES[11]; extern const char *const MISC_NAMES[22]; +extern const char *const *ITEM_NAMES[4]; + extern const char *const ELEMENTAL_NAMES[6]; extern const char *const ATTRIBUTE_NAMES[10]; extern const char *const EFFECTIVENESS_NAMES[7]; @@ -527,6 +529,16 @@ extern const char *SPELL_CAST_COMPONENTS[2]; extern const char *const CAST_SPELL_DETAILS; +extern const char *const PARTY_FOUND; + +extern const char *const BACKPACKS_FULL_PRESS_KEY; + +extern const char *const HIT_A_KEY; + +extern const char *const GIVE_TREASURE_FORMATTING; + +extern const char *const X_FOUND_Y; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3 From c99a901f65dbb61ad961d8c70be41fd6620ca840 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Feb 2015 14:41:57 -0500 Subject: XEEN: More code for dismiss dialog --- engines/xeen/dialogs_dismiss.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_dismiss.cpp b/engines/xeen/dialogs_dismiss.cpp index 1317d84447..9323b46429 100644 --- a/engines/xeen/dialogs_dismiss.cpp +++ b/engines/xeen/dialogs_dismiss.cpp @@ -45,7 +45,8 @@ void Dismiss::execute() { _iconSprites.draw(w, 0, Common::Point(225, 120)); w.update(); - while (!_vm->shouldQuit()) { + bool breakFlag = false; + while (!_vm->shouldQuit() && !breakFlag) { do { events.updateGameCounter(); intf.draw3d(false); @@ -70,17 +71,14 @@ void Dismiss::execute() { ErrorScroll::show(_vm, CANT_DISMISS_LAST_CHAR, WT_NONFREEZED_WAIT); w.open(); } else { - Character tempChar = party._activeParty[_buttonValue]; - int charIndex = party._activeParty[_buttonValue]._rosterId; - -// party.sortParty(); - - // TODO + // Remove the character from the party + party._activeParty.remove_at(_buttonValue); + breakFlag = true; } break; } } else if (_buttonValue == Common::KEYCODE_ESCAPE) { - + breakFlag = true; } } } -- cgit v1.2.3 From 458bf83097036f90a090eb97194fad395ca3c8e1 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Feb 2015 22:11:23 -0500 Subject: XEEN: Restrict sprite drawing to window bounds --- engines/xeen/dialogs.cpp | 1 + engines/xeen/dialogs.h | 1 + engines/xeen/screen.h | 2 ++ engines/xeen/sprites.cpp | 31 ++++++++++++++++++++++--------- engines/xeen/sprites.h | 10 +++++++++- 5 files changed, 35 insertions(+), 10 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index 116054dfe7..77cdd92169 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -24,6 +24,7 @@ #include "xeen/dialogs.h" #include "xeen/events.h" #include "xeen/resources.h" +#include "xeen/screen.h" #include "xeen/xeen.h" namespace Xeen { diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h index c04b680ff1..6e809ba2dc 100644 --- a/engines/xeen/dialogs.h +++ b/engines/xeen/dialogs.h @@ -27,6 +27,7 @@ #include "common/stack.h" #include "common/rect.h" #include "xeen/sprites.h" +#include "xeen/xsurface.h" namespace Xeen { diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 526fd6f845..f8f11a44a4 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -80,6 +80,8 @@ public: void setBounds(const Common::Rect &r); + const Common::Rect &getBounds() { return _bounds; } + void open(); void close(); diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 7bffa68907..2c5279bebc 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -25,6 +25,7 @@ #include "common/memstream.h" #include "common/textconsole.h" #include "xeen/xeen.h" +#include "xeen/screen.h" #include "xeen/sprites.h" namespace Xeen { @@ -110,7 +111,8 @@ void SpriteResource::clear() { /** * Draws a frame using data at a specific offset in the sprite resource */ -void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, int flags) const { +void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, + const Common::Rect &bounds, int flags) const { // Get cell header Common::MemoryReadStream f(_data, _filesize); f.seek(offset); @@ -139,14 +141,14 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi if (lineLength == 0) { // Skip the specified number of scan lines yPos += f.readByte(); - } else if ((destPos.y + yPos) < 0 || (destPos.y + yPos) >= dest.h) { + } else if ((destPos.y + yPos) < bounds.top || (destPos.y + yPos) >= bounds.bottom) { // Skip over the bytes of the line f.skip(lineLength); } else { // Skip the transparent pixels at the beginning of the scan line int xPos = f.readByte() + xOffset; ++byteCount; - const byte *lineStartP = (const byte *)dest.getBasePtr(0, destPos.y + yPos); - const byte *lineEndP = (const byte *)dest.getBasePtr(dest.w, destPos.y + yPos); + const byte *lineStartP = (const byte *)dest.getBasePtr(bounds.left, destPos.y + yPos); + const byte *lineEndP = (const byte *)dest.getBasePtr(bounds.right, destPos.y + yPos); byte *destP = !flipped ? (byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos) : (byte *)dest.getBasePtr(destPos.x + width - xPos, destPos.y + yPos); @@ -247,17 +249,27 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi dest.addDirtyRect(r); } +void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, + int flags, int scale) const { + draw(dest, frame, destPos, Common::Rect(0, 0, dest.w, dest.h), flags, scale); +} + +void SpriteResource::draw(Window &dest, int frame, const Common::Point &destPos, + int flags, int scale) const { + draw(dest, frame, destPos, dest.getBounds(), flags, scale); +} + /** * Draw the sprite onto the given surface */ void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, - int flags, int scale) const { + const Common::Rect &bounds, int flags, int scale) const { assert(scale != 0x8000); // TODO: TO test when I find scale value used if (scale == 0) { - drawOffset(dest, _index[frame]._offset1, destPos, flags); + drawOffset(dest, _index[frame]._offset1, destPos, bounds, flags); if (_index[frame]._offset2) - drawOffset(dest, _index[frame]._offset2, destPos, flags); + drawOffset(dest, _index[frame]._offset2, destPos, bounds, flags); } else { // Get the bounds for the surface and create a temporary one Common::MemoryReadStream f(_data, _filesize); @@ -267,12 +279,13 @@ void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPo int yOffset = f.readUint16LE(); int height = f.readUint16LE(); XSurface tempSurface(xOffset + width, yOffset + height); + Common::Rect tempBounds(0, 0, tempSurface.w, tempSurface.h); // Draw sprite into temporary surface tempSurface.fillRect(Common::Rect(0, 0, width, height), 0); - drawOffset(tempSurface, _index[frame]._offset1, Common::Point(), flags); + drawOffset(tempSurface, _index[frame]._offset1, Common::Point(), tempBounds, flags); if (_index[frame]._offset2) - drawOffset(tempSurface, _index[frame]._offset2, Common::Point(), flags); + drawOffset(tempSurface, _index[frame]._offset2, Common::Point(), tempBounds, flags); // TODO: I don't currently know the algorithm the original used for scaling. // This is a best fit estimate that every increment of the scale field diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index 15a3b7ca87..7fc6793499 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -32,6 +32,7 @@ namespace Xeen { class XeenEngine; +class Window; enum SpriteFlags { SPRFLAG_2000 = 0x2000, SPRFLAG_4000 = 0x4000, SPRFLAG_HORIZ_FLIPPED = 0x8000, SPRFLAG_RESIZE = 0x10000 }; @@ -47,7 +48,11 @@ private: void load(Common::SeekableReadStream &f); - void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, int flags) const; + void draw(XSurface &dest, int frame, const Common::Point &destPos, + const Common::Rect &bounds, int flags = 0, int scale = 0) const; + + void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, + const Common::Rect &bounds, int flags) const; public: SpriteResource(); SpriteResource(const Common::String &filename); @@ -65,6 +70,9 @@ public: void draw(XSurface &dest, int frame, const Common::Point &destPos, int flags = 0, int scale = 0) const; + void draw(Window &dest, int frame, const Common::Point &destPos, + int flags = 0, int scale = 0) const; + void draw(XSurface &dest, int frame) const; int size() const { return _index.size(); } -- cgit v1.2.3 From 6126d45b0b4fdc50ca81308f80181550da0f455c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Feb 2015 10:57:15 -0500 Subject: XEEN: Remove redundant comment from drawList method --- engines/xeen/screen.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 3b3ea6969b..ac1f0c476b 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -196,7 +196,6 @@ void Window::drawList(DrawStruct *items, int count) { pt.x += _innerBounds.left; pt.y += _innerBounds.top; - // TODO: There are two sprite calls in this method. Figure out why items->_sprites->draw(*this, items->_frame, pt, items->_flags, items->_scale); } } -- cgit v1.2.3 From 3f27fd8bb766f9ac76fb5e450e62c4493ef121a9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Feb 2015 11:45:00 -0500 Subject: XEEN: Fix horizontal positioning for flipped images --- engines/xeen/sprites.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 2c5279bebc..93c7e426f1 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -151,7 +151,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi const byte *lineEndP = (const byte *)dest.getBasePtr(bounds.right, destPos.y + yPos); byte *destP = !flipped ? (byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos) : - (byte *)dest.getBasePtr(destPos.x + width - xPos, destPos.y + yPos); + (byte *)dest.getBasePtr(destPos.x + xOffset + width - xPos, destPos.y + yPos); while (byteCount < lineLength) { // The next byte is an opcode that determines what -- cgit v1.2.3 From c15ca5ca50d42ad73ab32243a9bd092a0c86cb72 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Feb 2015 18:33:36 -0500 Subject: XEEN: Fix compiler warning --- engines/xeen/combat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 4b9ddd6323..471fefd751 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -1623,7 +1623,7 @@ bool Combat::hitMonster(Character &c, RangeType rangeType) { Map &map = *_vm->_map; getWeaponDamage(c, rangeType); int chance = c.statBonus(c.getStat(ACCURACY)) + _hitChanceBonus; - int divisor; + int divisor = 0; switch (c._class) { case CLASS_KNIGHT: -- cgit v1.2.3 From 3e05d9008e88b108a55455643900939f91174670 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Feb 2015 20:37:56 -0500 Subject: XEEN: Merge scaling code from XSurface into sprite drawing code --- engines/xeen/sprites.cpp | 183 ++++++++++++++++++++++++++++++---------------- engines/xeen/sprites.h | 16 ++-- engines/xeen/xsurface.cpp | 142 ----------------------------------- engines/xeen/xsurface.h | 7 -- 4 files changed, 130 insertions(+), 218 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 93c7e426f1..d75eb9cb4f 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -33,10 +33,14 @@ namespace Xeen { SpriteResource::SpriteResource() { _filesize = 0; _data = nullptr; + _scaledWidth = _scaledHeight = 0; + Common::fill(&_lineDist[0], &_lineDist[SCREEN_WIDTH], false); } SpriteResource::SpriteResource(const Common::String &filename) { _data = nullptr; + _scaledWidth = _scaledHeight = 0; + Common::fill(&_lineDist[0], &_lineDist[SCREEN_WIDTH], false); load(filename); } @@ -112,7 +116,7 @@ void SpriteResource::clear() { * Draws a frame using data at a specific offset in the sprite resource */ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, - const Common::Rect &bounds, int flags) const { + const Common::Rect &bounds, int flags, int scale) { // Get cell header Common::MemoryReadStream f(_data, _filesize); f.seek(offset); @@ -121,6 +125,14 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi int yOffset = f.readUint16LE(); int height = f.readUint16LE(); + // TODO: I don't currently know the algorithm the original used for scaling. + // This is a best fit estimate that every increment of the scale field + // reduces the size of a sprite by approximately 6.6% + int newScale = MAX(100.0 - 6.6 * scale, 0.0); + if (newScale == 0) + return; + setupScaling(newScale, xOffset + width, yOffset + height); + bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0; int xInc = flipped ? -1 : 1; @@ -134,24 +146,34 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi // Main loop int opr1, opr2; int32 pos; - for (int yPos = yOffset, byteCount = 0; yPos < height + yOffset; yPos++, byteCount = 0) { + int yIndex = yOffset; + int yPos = destPos.y + getScaledValue(yOffset); + for (int yCtr = 0, byteCount = 0; yCtr < height; ++yCtr, ++yIndex, byteCount = 0) { // The number of bytes in this scan line int lineLength = f.readByte(); if (lineLength == 0) { // Skip the specified number of scan lines - yPos += f.readByte(); - } else if ((destPos.y + yPos) < bounds.top || (destPos.y + yPos) >= bounds.bottom) { + int numLines = f.readByte(); + for (int idx = 0; idx < numLines; ++idx, ++yIndex, ++yCtr) { + if (_lineDist[yIndex]) + ++yPos; + } + } else if (destPos.y < bounds.top || yPos >= bounds.bottom + || !_lineDist[yIndex]) { // Skip over the bytes of the line f.skip(lineLength); } else { + const byte *lineStartP = (const byte *)dest.getBasePtr(bounds.left, yPos); + const byte *lineEndP = (const byte *)dest.getBasePtr(bounds.right, yPos); + // Skip the transparent pixels at the beginning of the scan line int xPos = f.readByte() + xOffset; ++byteCount; - const byte *lineStartP = (const byte *)dest.getBasePtr(bounds.left, destPos.y + yPos); - const byte *lineEndP = (const byte *)dest.getBasePtr(bounds.right, destPos.y + yPos); - byte *destP = !flipped ? - (byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos) : - (byte *)dest.getBasePtr(destPos.x + xOffset + width - xPos, destPos.y + yPos); + int xAmt = getScaledValue(flipped ? xOffset + width - xPos : xPos); + int xIndex = 0; + + byte *destP = (byte *)dest.getBasePtr(destPos.x + xAmt, yPos); + ++yPos; while (byteCount < lineLength) { // The next byte is an opcode that determines what @@ -169,18 +191,22 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi byte b = f.readByte(); ++byteCount; - if (destP >= lineStartP && destP < lineEndP) - *destP = b; - destP += xInc; + if (_lineDist[xIndex++]) { + if (destP >= lineStartP && destP < lineEndP) + *destP = b; + destP += xInc; + } } break; case 2: // The following byte is an index into the color table, draw it len + 3 times. opr1 = f.readByte(); ++byteCount; for (int i = 0; i < len + 3; ++i, ++xPos) { - if (destP >= lineStartP && destP < lineEndP) - *destP = opr1; - destP += xInc; + if (_lineDist[xIndex++]) { + if (destP >= lineStartP && destP < lineEndP) + *destP = opr1; + destP += xInc; + } } break; @@ -191,9 +217,11 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi for (int i = 0; i < len + 4; ++i, ++xPos) { byte b = f.readByte(); - if (destP >= lineStartP && destP < lineEndP) - *destP = b; - destP += xInc; + if (_lineDist[xIndex++]) { + if (destP >= lineStartP && destP < lineEndP) + *destP = b; + destP += xInc; + } } f.seek(pos, SEEK_SET); @@ -204,19 +232,29 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi opr2 = f.readByte(); ++byteCount; for (int i = 0; i < len + 2; ++i, xPos += 2) { if (destP < lineStartP || destP >= (lineEndP - 1)) { - destP += 2 * xInc; + if (_lineDist[xIndex++]) + destP += xInc; + if (_lineDist[xIndex++]) + destP += xInc; } else { - *destP = opr1; - destP += xInc; - *destP = opr2; - destP += xInc; + if (_lineDist[xIndex++]) { + *destP = opr1; + destP += xInc; + } + if (_lineDist[xIndex++]) { + *destP = opr2; + destP += xInc; + } } } break; case 5: // Skip len + 1 pixels filling them with the transparent color. - xPos += len + 1; - destP += (len + 1) * xInc; + for (int idx = 0; idx < (len + 1); ++idx) { + if (_lineDist[xIndex++]) + destP += xInc; + ++xPos; + } break; case 6: // Pattern command. @@ -227,9 +265,11 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi opr1 = f.readByte(); ++byteCount; for (int i = 0; i < len + 3; ++i, ++xPos) { - if (destP >= lineStartP && destP < lineEndP) - *destP = opr1; - destP += xInc; + if (_lineDist[xIndex++]) { + if (destP >= lineStartP && destP < lineEndP) + *destP = opr1; + destP += xInc; + } opr1 += patternSteps[cmd + (i % 2)]; } break; @@ -242,20 +282,21 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi } } - Common::Rect r(Common::Rect(destPos.x + xOffset, destPos.y + yOffset, - destPos.x + xOffset + width, destPos.y + yOffset + height)); + Common::Rect r(Common::Rect( + destPos.x + getScaledValue(xOffset), destPos.y + getScaledValue(yOffset), + destPos.x + getScaledValue(xOffset + width), destPos.y + getScaledValue(yOffset + height))); r.clip(Common::Rect(0, 0, dest.w, dest.h)); if (!r.isEmpty()) dest.addDirtyRect(r); } void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, - int flags, int scale) const { + int flags, int scale) { draw(dest, frame, destPos, Common::Rect(0, 0, dest.w, dest.h), flags, scale); } void SpriteResource::draw(Window &dest, int frame, const Common::Point &destPos, - int flags, int scale) const { + int flags, int scale) { draw(dest, frame, destPos, dest.getBounds(), flags, scale); } @@ -263,44 +304,58 @@ void SpriteResource::draw(Window &dest, int frame, const Common::Point &destPos, * Draw the sprite onto the given surface */ void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, - const Common::Rect &bounds, int flags, int scale) const { - assert(scale != 0x8000); // TODO: TO test when I find scale value used - - if (scale == 0) { - drawOffset(dest, _index[frame]._offset1, destPos, bounds, flags); - if (_index[frame]._offset2) - drawOffset(dest, _index[frame]._offset2, destPos, bounds, flags); - } else { - // Get the bounds for the surface and create a temporary one - Common::MemoryReadStream f(_data, _filesize); - f.seek(_index[frame]._offset1); - int xOffset = f.readUint16LE(); - int width = f.readUint16LE(); - int yOffset = f.readUint16LE(); - int height = f.readUint16LE(); - XSurface tempSurface(xOffset + width, yOffset + height); - Common::Rect tempBounds(0, 0, tempSurface.w, tempSurface.h); - - // Draw sprite into temporary surface - tempSurface.fillRect(Common::Rect(0, 0, width, height), 0); - drawOffset(tempSurface, _index[frame]._offset1, Common::Point(), tempBounds, flags); - if (_index[frame]._offset2) - drawOffset(tempSurface, _index[frame]._offset2, Common::Point(), tempBounds, flags); - - // TODO: I don't currently know the algorithm the original used for scaling. - // This is a best fit estimate that every increment of the scale field - // reduces the size of a sprite by approximately 6.6% - int newScale = MAX(100.0 - 6.6 * scale, 0.0); - if (newScale > 0) - tempSurface.transBlitTo(dest, Common::Point(), newScale, 0); - } + const Common::Rect &bounds, int flags, int scale) { + // TODO: TO test when I find sprites using scale values and flags + assert(scale != 0x8000); + assert(scale >= 0); +// assert((flags & SPRFLAG_2000) == 0); + + drawOffset(dest, _index[frame]._offset1, destPos, bounds, flags, scale); + if (_index[frame]._offset2) + drawOffset(dest, _index[frame]._offset2, destPos, bounds, flags, scale); } /** * Draw the sprite onto the given surface */ -void SpriteResource::draw(XSurface &dest, int frame) const { +void SpriteResource::draw(XSurface &dest, int frame) { draw(dest, frame, Common::Point()); } +void SpriteResource::setupScaling(int scale, int frameWidth, int frameHeight) { + int highestDim = MAX(frameWidth, frameHeight); + int distCtr = 0; + int distIndex = 0; + _scaledWidth = _scaledHeight = 0; + + do { + distCtr += scale; + if (distCtr < 100) { + _lineDist[distIndex] = false; + } else { + _lineDist[distIndex] = true; + distCtr -= 100; + + if (distIndex < frameWidth) + ++_scaledWidth; + + if (distIndex < frameHeight) + ++_scaledHeight; + } + } while (++distIndex < highestDim); +} + +/** + * Returns a scaled value based on a passed in x or y distance + */ +int SpriteResource::getScaledValue(int xy) { + int newVal = 0; + for (int idx = 0; idx < xy; ++idx) { + if (_lineDist[idx]) + ++newVal; + } + + return newVal; +} + } // End of namespace Xeen diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index 7fc6793499..2d9fe2f8c6 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -45,14 +45,20 @@ private: Common::Array<IndexEntry> _index; int32 _filesize; byte *_data; + bool _lineDist[320]; + int _scaledWidth, _scaledHeight; void load(Common::SeekableReadStream &f); void draw(XSurface &dest, int frame, const Common::Point &destPos, - const Common::Rect &bounds, int flags = 0, int scale = 0) const; + const Common::Rect &bounds, int flags = 0, int scale = 0); void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, - const Common::Rect &bounds, int flags) const; + const Common::Rect &bounds, int flags, int scale); + + void setupScaling(int scale, int frameWidth, int frameHeight); + + int getScaledValue(int xy); public: SpriteResource(); SpriteResource(const Common::String &filename); @@ -68,12 +74,12 @@ public: void clear(); void draw(XSurface &dest, int frame, const Common::Point &destPos, - int flags = 0, int scale = 0) const; + int flags = 0, int scale = 0); void draw(Window &dest, int frame, const Common::Point &destPos, - int flags = 0, int scale = 0) const; + int flags = 0, int scale = 0); - void draw(XSurface &dest, int frame) const; + void draw(XSurface &dest, int frame); int size() const { return _index.size(); } diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp index 7060a6326a..04a264a80c 100644 --- a/engines/xeen/xsurface.cpp +++ b/engines/xeen/xsurface.cpp @@ -55,152 +55,10 @@ void XSurface::create(XSurface *s, const Common::Rect &bounds) { _freeFlag = false; } - -void XSurface::transBlitTo(XSurface &dest) const { - transBlitTo(dest, Common::Point()); -} - void XSurface::blitTo(XSurface &dest) const { blitTo(dest, Common::Point()); } -void XSurface::transBlitTo(XSurface &dest, const Common::Point &destPos) const { - if (dest.getPixels() == nullptr) - dest.create(w, h); - - for (int yp = 0; yp < h; ++yp) { - const byte *srcP = (const byte *)getBasePtr(0, yp); - byte *destP = (byte *)dest.getBasePtr(destPos.x, destPos.y + yp); - - for (int xp = 0; xp < w; ++xp, ++srcP, ++destP) { - if (*srcP != 0) - *destP = *srcP; - } - } - - dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y)); -} - -void XSurface::transBlitTo(XSurface &dest, const Common::Point &destPos, - int scale, int transparentColor) { - int destX = destPos.x, destY = destPos.y; - int frameWidth = this->w; - int frameHeight = this->h; - int direction = 1; - - int highestDim = MAX(frameWidth, frameHeight); - bool lineDist[SCREEN_WIDTH]; - int distXCount = 0, distYCount = 0; - - if (scale != 0) { - int distCtr = 0; - int distIndex = 0; - do { - distCtr += scale; - if (distCtr < 100) { - lineDist[distIndex] = false; - } - else { - lineDist[distIndex] = true; - distCtr -= 100; - - if (distIndex < frameWidth) - ++distXCount; - - if (distIndex < frameHeight) - ++distYCount; - } - } while (++distIndex < highestDim); - - destX += (this->w - distXCount) / 2; - destY += (this->h - distYCount) / 2; - } - - // Start of draw logic for scaled sprites - const byte *srcPixelsP = (const byte *)getPixels(); - - int destRight = dest.w - 1; - int destBottom = dest.h - 1; - - // Check x bounding area - int spriteLeft = 0; - int spriteWidth = distXCount; - int widthAmount = destX + distXCount - 1; - - if (destX < 0) { - spriteWidth += destX; - spriteLeft -= destX; - } - widthAmount -= destRight; - if (widthAmount > 0) - spriteWidth -= widthAmount; - - if (spriteWidth <= 0) - return; - - // Check y bounding area - int spriteTop = 0; - int spriteHeight = distYCount; - int heightAmount = destY + distYCount - 1; - - if (destY < 0) { - spriteHeight += destY; - spriteTop -= destY; - } - heightAmount -= destBottom; - if (heightAmount > 0) - spriteHeight -= heightAmount; - int spriteBottom = spriteTop + spriteHeight; - - if (spriteHeight <= 0) - return; - - byte *destPixelsP = (byte *)dest.getBasePtr(destX + spriteLeft, destY + spriteTop); - int destWidth = 0, destHeight = 0; - - spriteLeft = spriteLeft * direction; - - // Loop through the lines of the sprite - for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += this->pitch) { - if (!lineDist[yp]) - // Not a display line, so skip it - continue; - // Check whether the sprite line is in the display range - ++sprY; - if ((sprY >= spriteBottom) || (sprY < spriteTop)) - continue; - - // Found a line to display. Loop through the pixels - const byte *srcP = srcPixelsP; - byte *destP = destPixelsP; - ++destHeight; - - for (int xp = 0, sprX = 0; xp < frameWidth; ++xp, ++srcP) { - if (xp < spriteLeft) - // Not yet reached start of display area - continue; - if (!lineDist[sprX++]) - // Not a display pixel - continue; - - if (*srcP != transparentColor) - *destP = *srcP; - - destP += direction; - } - - // Keep track of widest line drawn - destWidth = MAX(destP - destPixelsP, destWidth); - - // Move to the next destination line - destPixelsP += dest.pitch; - } - - // Add a dirty rect for the affected area - dest.addDirtyRect(Common::Rect(destX + spriteLeft, destY + spriteTop, - destX + spriteLeft + destWidth, destY + spriteTop + destHeight)); -} - void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const { if (dest.getPixels() == nullptr) dest.create(w, h); diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h index 61f4f96cb1..d8747d4372 100644 --- a/engines/xeen/xsurface.h +++ b/engines/xeen/xsurface.h @@ -44,13 +44,6 @@ public: void create(XSurface *s, const Common::Rect &bounds); - void transBlitTo(XSurface &dest) const; - - void transBlitTo(XSurface &dest, const Common::Point &destPos) const; - - void transBlitTo(XSurface &dest, const Common::Point &destPos, - int scale, int transparentColor); - void blitTo(XSurface &dest, const Common::Point &destPos) const; void blitTo(XSurface &dest) const; -- cgit v1.2.3 From 2d2fc3f9ed100fab85e736555048a62ac1e00dcd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Feb 2015 22:58:37 -0500 Subject: XEEN: Add horizontal placement fix for scaled sprites --- engines/xeen/sprites.cpp | 5 ++++- engines/xeen/sprites.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index d75eb9cb4f..b596432992 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -115,7 +115,7 @@ void SpriteResource::clear() { /** * Draws a frame using data at a specific offset in the sprite resource */ -void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, +void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &pt, const Common::Rect &bounds, int flags, int scale) { // Get cell header Common::MemoryReadStream f(_data, _filesize); @@ -133,6 +133,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi return; setupScaling(newScale, xOffset + width, yOffset + height); + Common::Point destPos = pt; + destPos.x += (xOffset + width - _scaledWidth) / 2; + bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0; int xInc = flipped ? -1 : 1; diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index 2d9fe2f8c6..0e3a3c3059 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -53,7 +53,7 @@ private: void draw(XSurface &dest, int frame, const Common::Point &destPos, const Common::Rect &bounds, int flags = 0, int scale = 0); - void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, + void drawOffset(XSurface &dest, uint16 offset, const Common::Point &pt, const Common::Rect &bounds, int flags, int scale); void setupScaling(int scale, int frameWidth, int frameHeight); -- cgit v1.2.3 From ddf71710016baaf9989c10b79e5e313464adbdf9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Feb 2015 22:59:05 -0500 Subject: XEEN: Fix placement of objects in setIndoorsObjects --- engines/xeen/interface_map.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 8032369cc6..249dc3a42b 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -2760,8 +2760,8 @@ void InterfaceMap::setIndoorsObjects() { } else if (_wo[20] && _wo[17]) { } else if (_wo[23] && _wo[17]) { } else if (!_wo[12] && !_wo[8] && _indoorList._objects9._frame == -1) { - _indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][9]; - _indoorList._objects9._y = MAP_OBJECT_Y[listOffset][9]; + _indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][10]; + _indoorList._objects9._y = MAP_OBJECT_Y[listOffset][10]; _indoorList._objects9._frame = mazeObject._frame; _indoorList._objects9._sprites = mazeObject._sprites; _indoorList._objects9._flags &= ~SPRFLAG_HORIZ_FLIPPED; @@ -2779,8 +2779,8 @@ void InterfaceMap::setIndoorsObjects() { } else if (_wo[14] && _wo[9]) { } else if (_wo[19] && _wo[9]) { } else if (_indoorList._objects10._frame == -1) { - _indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][10]; - _indoorList._objects10._y = MAP_OBJECT_Y[listOffset][10]; + _indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][9]; + _indoorList._objects10._y = MAP_OBJECT_Y[listOffset][9]; _indoorList._objects10._frame = mazeObject._frame; _indoorList._objects10._sprites = mazeObject._sprites; _indoorList._objects10._flags &= ~SPRFLAG_HORIZ_FLIPPED; -- cgit v1.2.3 From 9725fc57252b6dd4529e5f8e45519ac6fc480a12 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 22 Feb 2015 23:45:11 -0500 Subject: XEEN: Renaming and move flags used for UI indicators --- engines/xeen/combat.cpp | 10 ++++++---- engines/xeen/combat.h | 2 ++ engines/xeen/interface.cpp | 28 +++++++++++++++------------- engines/xeen/interface.h | 2 +- engines/xeen/spells.cpp | 2 +- engines/xeen/sprites.cpp | 4 +++- engines/xeen/town.cpp | 4 ++-- engines/xeen/xeen.cpp | 6 ++---- engines/xeen/xeen.h | 2 -- 9 files changed, 32 insertions(+), 28 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 471fefd751..254c33fa0c 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -123,6 +123,8 @@ Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.vo _attackWeapon = nullptr; _attackWeaponId = 0; _hitChanceBonus = 0; + _dangerPresent = false; + _moveMonsters = false; } void Combat::clear() { @@ -437,7 +439,7 @@ void Combat::moveMonsters() { Map &map = *_vm->_map; Party &party = *_vm->_party; - if (!_vm->_moveMonsters) + if (!_moveMonsters) return; intf._tillMove = 0; @@ -448,7 +450,7 @@ void Combat::moveMonsters() { Common::fill(&_monsterMoved[0], &_monsterMoved[MAX_NUM_MONSTERS], false); Common::fill(&_rangeAttacking[0], &_rangeAttacking[MAX_NUM_MONSTERS], false); Common::fill(&_gmonHit[0], &_gmonHit[36], -1); - _vm->_dangerSenseAllowed = false; + _dangerPresent = false; for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) { MazeMonster &monster = map._mobData._monsters[idx]; @@ -469,7 +471,7 @@ void Combat::moveMonsters() { MonsterStruct &monsterData = map._monsterData[monster._spriteId]; if (pt == monster._position) { - _vm->_dangerSenseAllowed = true; + _dangerPresent = true; if ((monster._isAttacking || _vm->_mode == MODE_SLEEPING) && !_monsterMoved[idx]) { if (party._mazePosition.x == pt.x || party._mazePosition.y == pt.y) { @@ -704,7 +706,7 @@ void Combat::moveMonster(int monsterId, const Common::Point &pt) { Map &map = *_vm->_map; MazeMonster &monster = map._mobData._monsters[monsterId]; - if (_monsterMap[pt.y][pt.x] < 3 && !monster._damageType && _vm->_moveMonsters) { + if (_monsterMap[pt.y][pt.x] < 3 && !monster._damageType && _moveMonsters) { ++_monsterMap[pt.y][pt.x]; --_monsterMap[monster._position.y][monster._position.x]; monster._position = pt; diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 466152a70e..f78e928aa4 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -118,6 +118,8 @@ public: int _attackWeaponId; File _missVoc, _pow1Voc; int _hitChanceBonus; + bool _dangerPresent; + bool _moveMonsters; public: Combat(XeenEngine *vm); diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 1b3ee4f32c..434320762d 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -143,7 +143,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _flipUIFrame = 0; _face1UIFrame = 0; _face2UIFrame = 0; - _batUIFrame = 0; + _levitateUIFrame = 0; _spotDoorsUIFrame = 0; _dangerSenseUIFrame = 0; _face1State = _face2State = 0; @@ -327,11 +327,11 @@ void Interface::perform() { switch (_buttonValue) { case Common::KEYCODE_TAB: // Stop mosters doing any movement - _vm->_moveMonsters = false; + combat._moveMonsters = false; if (ControlPanel::show(_vm) == -1) { _vm->_quitMode = 2; } else { - _vm->_moveMonsters = 1; + combat._moveMonsters = 1; } break; @@ -488,9 +488,9 @@ void Interface::perform() { case Common::KEYCODE_EQUALS: case Common::KEYCODE_KP_EQUALS: // Toggle minimap - _vm->_moveMonsters = false; + combat._moveMonsters = false; party._automapOn = !party._automapOn; - _vm->_moveMonsters = true; + combat._moveMonsters = true; break; case Common::KEYCODE_b: @@ -547,9 +547,9 @@ void Interface::perform() { case Common::KEYCODE_i: // Show Info dialog - _vm->_moveMonsters = false; + combat._moveMonsters = false; InfoDialog::show(_vm); - _vm->_moveMonsters = true; + combat._moveMonsters = true; break; case Common::KEYCODE_m: @@ -1237,7 +1237,7 @@ void Interface::draw3d(bool updateFlag) { if (_flipUIFrame == 0) _flipWater = !_flipWater; if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_COMBAT) && - !combat._monstersAttacking && _vm->_moveMonsters) { + !combat._monstersAttacking && combat._moveMonsters) { if (--_tillMove == 0) combat.moveMonsters(); } @@ -1270,7 +1270,7 @@ void Interface::draw3d(bool updateFlag) { if (combat._attackMonsters[0] != -1 || combat._attackMonsters[1] != -1 || combat._attackMonsters[2] != -1) { if ((_vm->_mode == MODE_1 || _vm->_mode == MODE_SLEEPING) && - !combat._monstersAttacking && !_charsShooting && _vm->_moveMonsters) { + !combat._monstersAttacking && !_charsShooting && combat._moveMonsters) { doCombat(); if (scripts._eventSkipped) scripts.checkEvents(); @@ -1743,16 +1743,18 @@ void Interface::drawMiniMap() { * Draw the display borders */ void Interface::assembleBorder() { + Combat &combat = *_vm->_combat; Resources &res = *_vm->_resources; Screen &screen = *_vm->_screen; // Draw the outer frame res._globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8)); - // Draw the animating bat character used to show when levitate is active - _borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16, + // Draw the animating bat character on the left screen edge to indicate + // that the party is being levitated + _borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _levitateUIFrame + 16 : 16, Common::Point(0, 82)); - _batUIFrame = (_batUIFrame + 1) % 12; + _levitateUIFrame = (_levitateUIFrame + 1) % 12; // Draw UI element to indicate whether can spot hidden doors _borderSprites.draw(screen, @@ -1762,7 +1764,7 @@ void Interface::assembleBorder() { // Draw UI element to indicate whether can sense danger _borderSprites.draw(screen, - (_vm->_dangerSenseAllowed && _vm->_party->checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40, + (combat._dangerPresent && _vm->_party->checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40, Common::Point(107, 9)); _dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12; diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 80b798047c..66a40c23cf 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -115,7 +115,7 @@ public: int _face1UIFrame, _face2UIFrame; int _spotDoorsUIFrame; int _dangerSenseUIFrame; - int _batUIFrame; + int _levitateUIFrame; bool _upDoorText; Common::String _screenText; byte _tillMove; diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index d2a2af31c0..25aae11af2 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -151,7 +151,7 @@ int Spells::castSpell(Character *c, int spellId) { } } - _vm->_moveMonsters = 1; + combat._moveMonsters = 1; intf._tillMove = oldTillMove; return result; } diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index b596432992..597d4dff8e 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -134,7 +134,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi setupScaling(newScale, xOffset + width, yOffset + height); Common::Point destPos = pt; - destPos.x += (xOffset + width - _scaledWidth) / 2; + if (!(flags & SPRFLAG_2000)) { + destPos.x += (xOffset + width - _scaledWidth) / 2; + } bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0; int xInc = flipped ? -1 : 1; diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 3a8b6d8231..0934aef34f 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -217,7 +217,7 @@ int Town::townAction(int actionId) { intf._face1UIFrame = intf._face2UIFrame = 0; intf._dangerSenseUIFrame = 0; intf._spotDoorsUIFrame = 0; - intf._batUIFrame = 0; + intf._levitateUIFrame = 0; _townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos); if (actionId == 0 && isDarkCc) { @@ -1148,7 +1148,7 @@ void Town::drawTownAnim(bool flag) { intf._face2UIFrame = 0; intf._dangerSenseUIFrame = 0; intf._spotDoorsUIFrame = 0; - intf._batUIFrame = 0; + intf._levitateUIFrame = 0; intf.assembleBorder(); } diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index a3240bf8b5..1410d65627 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -52,9 +52,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _town = nullptr; _eventData = nullptr; _quitMode = 0; - _dangerSenseAllowed = false; _noDirectionSense = false; - _moveMonsters = false; _mode = MODE_0; _startupWindowActive = false; } @@ -315,13 +313,13 @@ void XeenEngine::play() { _screen->_windows[0].update(); _events->setCursor(0); - _moveMonsters = true; + _combat->_moveMonsters = true; if (_mode == MODE_0) { _mode = MODE_1; _screen->fadeIn(4); } - _moveMonsters = true; + _combat->_moveMonsters = true; gameLoop(); } diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 76cb1c1159..2d995a1dd3 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -153,9 +153,7 @@ public: GameEvent _gameEvent; Common::SeekableReadStream *_eventData; int _quitMode; - bool _dangerSenseAllowed; bool _noDirectionSense; - bool _moveMonsters; bool _startupWindowActive; public: XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); -- cgit v1.2.3 From cba25ea458e428d2e9c1e6e30bb86a5c9da72b54 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 23 Feb 2015 19:35:24 -0500 Subject: XEEN: Fix placement of enemies --- engines/xeen/interface_map.cpp | 64 +++++++++++++++++++++++++++++++++++++++++- engines/xeen/sprites.cpp | 4 +-- 2 files changed, 64 insertions(+), 4 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 249dc3a42b..a54b95fb64 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -2555,6 +2555,68 @@ void InterfaceMap::setIndoorsMonsters() { } } } + + _indoorList[153]._x += 58; + _indoorList[131]._x += 25; + _indoorList[105]._x += 9; + _indoorList[69]._x--; + _indoorList[61]._x -= 26; + _indoorList[64]._x += 23; + _indoorList[66]._x -= 58; + _indoorList[67]._x += 40; + _indoorList[100]._x -= 65; + _indoorList[101]._x -= 85; + _indoorList[102]._x += 49; + _indoorList[103]._x += 65; + _indoorList[128]._x -= 112; + _indoorList[129]._x += 98; + + if (combat._attackMonsters[1] != -1 && combat._attackMonsters[2] == -1) { + _indoorList[156]._x += 31; + _indoorList[150]._x -= 36; + } else { + _indoorList[156]._x -= 5; + _indoorList[150]._x -= 67; + } + + if (combat._attackMonsters[4] != -1 && combat._attackMonsters[5] == -1) { + _indoorList[132]._x += 8; + _indoorList[130]._x -= 23; + } else { + _indoorList[132]._x -= 7; + _indoorList[130]._x -= 38; + } + + if (combat._attackMonsters[7] != -1 && combat._attackMonsters[8] == -1) { + _indoorList[104]._x -= 16; + } else { + _indoorList[106]._x -= 8; + _indoorList[104]._x -= 24; + } + + if (combat._attackMonsters[10] != -1 && combat._attackMonsters[11] == -1) { + _indoorList[70]._x -= 5; + _indoorList[68]._x -= 13; + } else { + _indoorList[70]._x -= 9; + _indoorList[68]._x -= 17; + } + + if (combat._attackMonsters[22] == -1 && combat._attackMonsters[24] == -1) { + _indoorList[62]._x -= 27; + _indoorList[60]._x -= 37; + } else { + _indoorList[62]._x -= 34; + _indoorList[60]._x -= 41; + } + + if (combat._attackMonsters[23] != -1 && combat._attackMonsters[25] == -1) { + _indoorList[65]._x += 20; + _indoorList[63]._x -= 12; + } else { + _indoorList[65]._x += 16; + _indoorList[63]._x -= 16; + } } /** @@ -2577,7 +2639,7 @@ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster drawStruct._x = 0; } - drawStruct._flags &= SPRFLAG_HORIZ_FLIPPED | SPRFLAG_4000 | SPRFLAG_2000; + drawStruct._flags &= ~0xFFF; if (monster._effect2) drawStruct._flags = MONSTER_EFFECT_FLAGS[monster._effect2][monster._effect3]; } diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 597d4dff8e..b596432992 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -134,9 +134,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi setupScaling(newScale, xOffset + width, yOffset + height); Common::Point destPos = pt; - if (!(flags & SPRFLAG_2000)) { - destPos.x += (xOffset + width - _scaledWidth) / 2; - } + destPos.x += (xOffset + width - _scaledWidth) / 2; bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0; int xInc = flipped ? -1 : 1; -- cgit v1.2.3 From 20bdb154f60f590759627b4782e72e88d34bef2d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 23 Feb 2015 20:04:52 -0500 Subject: XEEN: Fix _newDay initialization --- engines/xeen/interface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 434320762d..e6305bfd88 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -182,7 +182,7 @@ void Interface::setup() { Party &party = *_vm->_party; party.loadActiveParty(); - party._newDay = party._minutes >= 300; + party._newDay = party._minutes < 300; } void Interface::startup() { @@ -581,7 +581,7 @@ void Interface::perform() { } void Interface::chargeStep() { - if (_vm->_party->_partyDead) { + if (!_vm->_party->_partyDead) { _vm->_party->changeTime(_vm->_map->_isOutdoors ? 10 : 1); if (!_tillMove) { _vm->_combat->moveMonsters(); -- cgit v1.2.3 From 5bb494fff10b17c6070cdd21e4f27903a6c1df74 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 25 Feb 2015 07:37:09 -0500 Subject: XEEN: Fix mosnters moving towards party --- engines/xeen/combat.cpp | 88 +++++++++++++++++++++++++++---------------------- engines/xeen/combat.h | 2 +- 2 files changed, 49 insertions(+), 41 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 254c33fa0c..69ffd7214a 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -462,7 +462,7 @@ void Combat::moveMonsters() { for (int loopNum = 0; loopNum < 2; ++loopNum) { int arrIndex = -1; for (int yDiff = 3; yDiff >= -3; --yDiff) { - for (int xDiff = 3; xDiff >= -3; --xDiff) { + for (int xDiff = -3; xDiff <= 3; ++xDiff) { Common::Point pt = party._mazePosition + Common::Point(xDiff, yDiff); ++arrIndex; @@ -484,43 +484,43 @@ void Combat::moveMonsters() { _rangeAttacking[idx] = true; } } - } - } - switch (party._mazeDirection) { - case DIR_NORTH: - case DIR_SOUTH: - if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]], - MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) { - // Move the monster - moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex])); - } else { - if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]], - arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0, - arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex], - idx)) - if (arrIndex >= 21 && arrIndex <= 27) { - moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0)); - } else { - moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex])); - } - } - break; + switch (party._mazeDirection) { + case DIR_NORTH: + case DIR_SOUTH: + if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]], + MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) { + // Move the monster + moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex])); + } else { + if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]], + arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0, + arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex], + idx)) + if (arrIndex >= 21 && arrIndex <= 27) { + moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0)); + } else { + moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex])); + } + } + break; - case DIR_EAST: - case DIR_WEST: - if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]], - arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0, - arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex], - idx)) { - if (arrIndex >= 21 && arrIndex <= 27) { - moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0)); - } else { - moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex])); + case DIR_EAST: + case DIR_WEST: + if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]], + arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0, + arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex], + idx)) { + if (arrIndex >= 21 && arrIndex <= 27) { + moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0)); + } else { + moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex])); + } + } else if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]], + MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) { + moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex])); + } } - } else if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]], - MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) { - moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex])); } } } @@ -660,6 +660,9 @@ void Combat::setupMonsterAttack(int monsterDataIndex, const Common::Point &pt) { } } +/** + * Determines whether a given monster can move + */ bool Combat::monsterCanMove(const Common::Point &pt, int wallShift, int xDiff, int yDiff, int monsterId) { Map &map = *_vm->_map; @@ -702,14 +705,19 @@ bool Combat::monsterCanMove(const Common::Point &pt, int wallShift, } } -void Combat::moveMonster(int monsterId, const Common::Point &pt) { +/** + * Moves a monster by a given delta amount if it's a valid move + */ +void Combat::moveMonster(int monsterId, const Common::Point &moveDelta) { Map &map = *_vm->_map; MazeMonster &monster = map._mobData._monsters[monsterId]; + Common::Point newPos = monster._position + moveDelta; - if (_monsterMap[pt.y][pt.x] < 3 && !monster._damageType && _moveMonsters) { - ++_monsterMap[pt.y][pt.x]; + if (_monsterMap[newPos.y][newPos.x] < 3 && !monster._damageType && _moveMonsters) { + // Adjust monster's position + ++_monsterMap[newPos.y][newPos.x]; --_monsterMap[monster._position.y][monster._position.x]; - monster._position = pt; + monster._position = newPos; _monsterMoved[monsterId] = true; } } @@ -754,7 +762,7 @@ void Combat::monsterOvercome() { MazeMonster &monster = map._mobData._monsters[idx]; int dataIndex = monster._spriteId; - if (monster._damageType != 0 && monster._damageType != 13) { + if (monster._damageType != DT_PHYSICAL && monster._damageType != DT_DRAGONSLEEP) { // Do a saving throw for monster if (dataIndex <= _vm->getRandomNumber(1, dataIndex + 50)) monster._damageType = 0; diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index f78e928aa4..d4cb87ea39 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -156,7 +156,7 @@ public: bool monsterCanMove(const Common::Point &pt, int wallShift, int v1, int v2, int monsterId); - void moveMonster(int monsterId, const Common::Point &pt); + void moveMonster(int monsterId, const Common::Point &moveDelta); void attackMonster(int monsterId); -- cgit v1.2.3 From 0e1bd4951b4912ab4b555228d2da410da8ad4697 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 25 Feb 2015 07:54:57 -0500 Subject: XEEN: Prevent double call to moveMonsters --- engines/xeen/interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index e6305bfd88..d69abef90f 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -583,7 +583,7 @@ void Interface::perform() { void Interface::chargeStep() { if (!_vm->_party->_partyDead) { _vm->_party->changeTime(_vm->_map->_isOutdoors ? 10 : 1); - if (!_tillMove) { + if (_tillMove) { _vm->_combat->moveMonsters(); } -- cgit v1.2.3 From ad33b8bb824803630bc37766da30047efa3f3f13 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 25 Feb 2015 19:42:29 -0500 Subject: XEEN: Fixed display of attacking monster names --- engines/xeen/combat.cpp | 15 ++++++++------- engines/xeen/map.cpp | 5 +++++ engines/xeen/map.h | 2 ++ engines/xeen/resources.cpp | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 69ffd7214a..df9ba9bb50 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -1073,11 +1073,8 @@ void Combat::setupCombatParty() { void Combat::setSpeedTable() { Map &map = *_vm->_map; Common::Array<int> charSpeeds; - bool flag = _whosSpeed != -1; - int oldSpeed = (_whosSpeed == -1) ? 0 : _speedTable[_whosSpeed]; - - Common::fill(&_speedTable[0], &_speedTable[12], -1); - Common::fill(&charSpeeds[0], &charSpeeds[12], -1); + bool hasSpeed = _whosSpeed != -1 && _whosSpeed < _speedTable.size(); + int oldSpeed = hasSpeed ? _speedTable[_whosSpeed] : 0; // Set up speeds for party membres int maxSpeed = 0; @@ -1101,6 +1098,8 @@ void Combat::setSpeedTable() { } } + // Populate the _speedTable list with the character/monster indexes + // in order of attacking speed _speedTable.clear(); for (; maxSpeed >= 0; --maxSpeed) { for (uint idx = 0; idx < charSpeeds.size(); ++idx) { @@ -1109,7 +1108,7 @@ void Combat::setSpeedTable() { } } - if (flag) { + if (hasSpeed) { if (_speedTable[_whosSpeed] != oldSpeed) { for (uint idx = 0; idx < charSpeeds.size(); ++idx) { if (oldSpeed == _speedTable[idx]) { @@ -1164,10 +1163,12 @@ Common::String Combat::getMonsterDescriptions() { if (_attackMonsters[idx] != -1) { MazeMonster &monster = map._mobData._monsters[_attackMonsters[idx]]; MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + int textColor = monster.getTextColor(); Common::String format = "\n\v020\f%2u%s\fd"; format.setChar('2' + idx, 3); - lines[idx] = Common::String::format(format.c_str(), monsterData._name.c_str()); + lines[idx] = Common::String::format(format.c_str(), textColor, + monsterData._name.c_str()); } } diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 10fba6d6b0..439d5a8251 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -662,6 +662,11 @@ MazeMonster::MazeMonster() { _attackSprites = nullptr; } +int MazeMonster::getTextColor() const { + warning("TODO: getTextColor"); + return 0; +} + /*------------------------------------------------------------------------*/ MazeWallItem::MazeWallItem() { diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 7faf59fc04..85a1b8b5a5 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -255,6 +255,8 @@ struct MazeMonster { SpriteResource *_attackSprites; MazeMonster(); + + int getTextColor() const; }; class MazeWallItem { diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index bcf408d893..2716f245b3 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1489,7 +1489,7 @@ const int NEW_CHARACTER_SPELLS[10][4] = { { 20, 1, -1, -1 } }; -const char *const COMBAT_DETAILS = "\r\f00\x03c\v000\t000\x02Combat%s%s%s\x1"; +const char *const COMBAT_DETAILS = "\r\f00\x3""c\v000\t000\x2""Combat%s%s%s\x1"; const char *NOT_ENOUGH_TO_CAST = "\x03c\v010Not enough %s to Cast %s"; const char *SPELL_CAST_COMPONENTS[2] = { "Spell Points", "Gems" }; -- cgit v1.2.3 From 9a8c4c55a3c4b243b95efb04eb72ca3808275b84 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 25 Feb 2015 20:08:26 -0500 Subject: XEEN: Add a MonsterStruct pointer to the MazeMonster class --- engines/xeen/combat.cpp | 16 ++++++++-------- engines/xeen/interface.cpp | 2 +- engines/xeen/interface_map.cpp | 8 ++++---- engines/xeen/map.cpp | 20 +++++++++++++++----- engines/xeen/map.h | 3 ++- engines/xeen/scripts.cpp | 1 + 6 files changed, 31 insertions(+), 19 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index df9ba9bb50..c3590e7cdd 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -468,7 +468,7 @@ void Combat::moveMonsters() { for (int idx = 0; idx < (int)map._mobData._monsters.size(); ++idx) { MazeMonster &monster = map._mobData._monsters[idx]; - MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + MonsterStruct &monsterData = *monster._monsterData; if (pt == monster._position) { _dangerPresent = true; @@ -667,7 +667,7 @@ bool Combat::monsterCanMove(const Common::Point &pt, int wallShift, int xDiff, int yDiff, int monsterId) { Map &map = *_vm->_map; MazeMonster &monster = map._mobData._monsters[monsterId]; - MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + MonsterStruct &monsterData = *monster._monsterData; Common::Point tempPos = pt; if (map._isOutdoors) { @@ -798,7 +798,7 @@ void Combat::attackMonster(int monsterId) { } MazeMonster &monster = map._mobData._monsters[monsterIndex]; - MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + MonsterStruct &monsterData = *monster._monsterData; if (monster._damageType) return; @@ -1089,7 +1089,7 @@ void Combat::setSpeedTable() { for (int monsterNum = 0; monsterNum < 3; ++monsterNum) { if (_attackMonsters[monsterNum] != -1) { MazeMonster &monster = map._mobData._monsters[_attackMonsters[monsterNum]]; - MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + MonsterStruct &monsterData = *monster._monsterData; charSpeeds.push_back(monsterData._speed); maxSpeed = MAX(maxSpeed, monsterData._speed); @@ -1162,7 +1162,7 @@ Common::String Combat::getMonsterDescriptions() { for (int idx = 0; idx < 3; ++idx) { if (_attackMonsters[idx] != -1) { MazeMonster &monster = map._mobData._monsters[_attackMonsters[idx]]; - MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + MonsterStruct &monsterData = *monster._monsterData; int textColor = monster.getTextColor(); Common::String format = "\n\v020\f%2u%s\fd"; @@ -1395,7 +1395,7 @@ void Combat::attack2(int damage, RangeType rangeType) { SoundManager &sound = *_vm->_sound; bool isDarkCc = _vm->_files->_isDarkCc; MazeMonster &monster = map._mobData._monsters[_monster2Attack]; - MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + MonsterStruct &monsterData = *monster._monsterData; bool monsterDied = false; if (!isDarkCc && damage && rangeType && monster._spriteId == 89) @@ -1669,7 +1669,7 @@ bool Combat::hitMonster(Character &c, RangeType rangeType) { assert(_monster2Attack != -1); MazeMonster &monster = map._mobData._monsters[_monster2Attack]; - MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + MonsterStruct &monsterData = *monster._monsterData; if (monster._damageType != DT_PHYSICAL) chance += 20; @@ -1737,7 +1737,7 @@ int Combat::getMonsterResistence(RangeType rangeType) { Map &map = *_vm->_map; assert(_monster2Attack != -1); MazeMonster &monster = map._mobData._monsters[_monster2Attack]; - MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + MonsterStruct &monsterData = *monster._monsterData; int resistence = 0, damage = 0; if (rangeType != RT_0 && rangeType != RT_3) { diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index d69abef90f..611eccb843 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -1924,7 +1924,7 @@ void Interface::doCombat() { if (++index == 5 && combat._attackMonsters[0] != -1) { MazeMonster &monster = map._mobData._monsters[combat._monster2Attack]; - MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + MonsterStruct &monsterData = *monster._monsterData; sound.playFX(monsterData._fx); } diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index a54b95fb64..de19a9957a 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -707,7 +707,7 @@ void InterfaceMap::animate3d() { MazeMonster &monster = map._mobData._monsters[idx]; if (!monster._damageType) { if (monster._frame < 8) { - MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + MonsterStruct &monsterData = *monster._monsterData; if (!monsterData._loopAnimation) { // Monster isn't specially looped, so cycle through the 8 frames monster._frame = (monster._frame + 1) % 8; @@ -755,7 +755,7 @@ void InterfaceMap::animate3d() { } else { monster._effect3 = (monster._effect3 + 1) % 8; if (monster._effect3 == 0) { - MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + MonsterStruct &monsterData = *monster._monsterData; monster._effect1 = monster._effect2 = monsterData._animationEffect; } } @@ -2625,7 +2625,7 @@ void InterfaceMap::setIndoorsMonsters() { */ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, SpriteResource *sprites, int frame, int defaultY) { - MonsterStruct &monsterData = _vm->_map->_monsterData[monster._spriteId]; + MonsterStruct &monsterData = *monster._monsterData; bool flying = monsterData._flying; drawStruct._frame = frame; @@ -3331,7 +3331,7 @@ void InterfaceMap::setOutdoorsMonsters() { // TODO: Double-check.. this section looks *weird* MazeMonster &monster = map._mobData._monsters[ds._frame]; - MonsterStruct &monsterData = map._monsterData[monster._spriteId]; + MonsterStruct &monsterData = *monster._monsterData; ds._frame = monster._frame; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 439d5a8251..2017978398 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -660,11 +660,20 @@ MazeMonster::MazeMonster() { _effect3 = 0; _sprites = nullptr; _attackSprites = nullptr; + _monsterData = nullptr; } +/** + * Return the text color to use when displaying the monster's name in combat + * to indicate how damaged they are + */ int MazeMonster::getTextColor() const { - warning("TODO: getTextColor"); - return 0; + if (_hp == _monsterData->_hp) + return 15; + else if (_hp >= (_monsterData->_hp / 2)) + return 9; + else + return 32; } /*------------------------------------------------------------------------*/ @@ -682,7 +691,7 @@ MazeWallItem::MazeWallItem() { MonsterObjectData::MonsterObjectData(XeenEngine *vm): _vm(vm) { } -void MonsterObjectData::synchronize(XeenSerializer &s, MonsterData monsterData) { +void MonsterObjectData::synchronize(XeenSerializer &s, MonsterData &monsterData) { Common::Array<MobStruct> mobStructs; MobStruct mobStruct; byte b; @@ -781,10 +790,11 @@ void MonsterObjectData::synchronize(XeenSerializer &s, MonsterData monsterData) mon._spriteId = _monsterSprites[mon._id]._spriteId; mon._sprites = &_monsterSprites[mon._id]._sprites; mon._attackSprites = &_monsterSprites[mon._id]._attackSprites; + mon._monsterData = &monsterData[mon._spriteId]; + mon._frame = _vm->getRandomNumber(7); - MonsterStruct &md = monsterData[mon._spriteId]; + MonsterStruct &md = *mon._monsterData; mon._hp = md._hp; - mon._frame = _vm->getRandomNumber(7); mon._effect1 = mon._effect2 = md._animationEffect; if (md._animationEffect) mon._effect3 = _vm->getRandomNumber(7); diff --git a/engines/xeen/map.h b/engines/xeen/map.h index 85a1b8b5a5..bd74837788 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -253,6 +253,7 @@ struct MazeMonster { int _effect3; SpriteResource *_sprites; SpriteResource *_attackSprites; + MonsterStruct *_monsterData; MazeMonster(); @@ -306,7 +307,7 @@ public: public: MonsterObjectData(XeenEngine *vm); - void synchronize(XeenSerializer &s, MonsterData monsterData); + void synchronize(XeenSerializer &s, MonsterData &monsterData); }; class HeadData { diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 7aab04c4c4..0d701fe3da 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -503,6 +503,7 @@ void Scripts::cmdSpawn(Common::Array<byte> ¶ms) { MazeMonster &monster = _vm->_map->_mobData._monsters[params[0]]; MonsterStruct &monsterData = _vm->_map->_monsterData[monster._spriteId]; + monster._monsterData = &monsterData; monster._position.x = params[1]; monster._position.y = params[2]; monster._frame = _vm->getRandomNumber(7); -- cgit v1.2.3 From 9b6749cab8908b45a9c7176faa5d142b72bcde0b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 25 Feb 2015 20:25:27 -0500 Subject: XEEN: Fix display of combat action buttons --- engines/xeen/interface.cpp | 10 +++------- engines/xeen/interface.h | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 611eccb843..47db309668 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -1223,7 +1223,7 @@ void Interface::bash(const Common::Point &pt, Direction direction) { drawParty(true); } -void Interface::draw3d(bool updateFlag) { +void Interface::draw3d(bool updateFlag, bool skipDelay) { Combat &combat = *_vm->_combat; EventsManager &events = *_vm->_events; Party &party = *_vm->_party; @@ -1282,11 +1282,7 @@ void Interface::draw3d(bool updateFlag) { // TODO: Save current scripts data? } - // TODO: Check use of updateFlag here. Original doesn't have it, but I - // wanted to ensure in places like the AutoMapDialog, that the draw3d - // doesn't result in the screen updating until the dialog has had - // a chance to full render itself - if (updateFlag) + if (!skipDelay) events.wait(2); } @@ -1871,7 +1867,7 @@ void Interface::doCombat() { _iconSprites.load("combat.icn"); for (int idx = 1; idx < 16; ++idx) - _mainList[idx]._sprites = nullptr; + _mainList[idx]._sprites = &_iconSprites; // Set the combat buttons setMainButtons(true); diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 66a40c23cf..f5e5cc34ee 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -140,7 +140,7 @@ public: void bash(const Common::Point &pt, Direction direction); - void draw3d(bool updateFlag); + void draw3d(bool updateFlag, bool skipDelay = false); void assembleBorder(); -- cgit v1.2.3 From b4c8c81a83eb95467def7de0e2c5d4c0d931d541 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 25 Feb 2015 21:54:03 -0500 Subject: XEEN: Properly reimplement nextChar --- engines/xeen/interface.cpp | 79 +++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 33 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 47db309668..74749d4f9a 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -1885,6 +1885,13 @@ void Interface::doCombat() { // Set up the combat party combat.setupCombatParty(); combat.setSpeedTable(); + + // Initialize arrays for character/monster states + combat._charsGone.resize(combat._speedTable.size()); + combat._charsBlocked.resize(combat._speedTable.size()); + Common::fill(&combat._charsGone[0], &combat._charsGone[0] + combat._speedTable.size(), 0); + Common::fill(&combat._charsBlocked[0], &combat._charsBlocked[0] + combat._speedTable.size(), false); + combat._whosSpeed = -1; combat._whosTurn = -1; resetHighlight(); @@ -1893,6 +1900,7 @@ void Interface::doCombat() { if (!party._dead) { combat.setSpeedTable(); + if (_tillMove) { combat.moveMonsters(); draw3d(true); @@ -2160,6 +2168,8 @@ void Interface::nextChar() { return; } + // Loop for potentially multiple monsters attacking until it's time + // for one of the party's turn for (;;) { // Check if party is dead party.checkPartyDead(); @@ -2168,50 +2178,53 @@ void Interface::nextChar() { break; } - if (combat._whosTurn < (int)combat._combatParty.size()) { - if (!combat.allHaveGone()) - highlightChar(combat._whosTurn); - break; - } else { - combat.attackMonster(0); - if (!party._dead) - party.checkPartyDead(); - - if (party._dead) - break; - } - - // Check the combat participants - bool resetFlag = false; - for (uint idx = 0; idx < combat._speedTable.size(); ++idx) { - // Mark the given character as haven taken their turn + int idx; + for (idx = 0; idx < (int)combat._speedTable.size(); ++idx) { if (combat._whosTurn != -1) { combat._charsGone[combat._whosTurn] = true; } - combat._whosSpeed %= combat._speedTable.size(); + combat._whosSpeed = (combat._whosSpeed + 1) % combat._speedTable.size(); combat._whosTurn = combat._speedTable[combat._whosSpeed]; - if (combat.allHaveGone()) { - if (combat.charsCantAct()) { - combat.setSpeedTable(); - combat._whosTurn = -1; - combat._whosSpeed = -1; - - combat._charsGone.resize(combat._speedTable.size()); - Common::fill(&combat._charsGone[0], &combat._charsGone[combat._charsGone.size()], 0); - resetFlag = true; - break; - } - return; - } else if (combat._whosTurn >= (int)combat._combatParty.size() || - !combat._combatParty[combat._whosTurn]->isDisabledOrDead()) { + idx = -1; break; } + + if (combat._whosTurn < (int)combat._combatParty.size()) { + if (!combat._combatParty[idx]->isDisabledOrDead()) + continue; + } + + break; } - if (party._dead) + if (idx == -1) { + if (!combat.charsCantAct()) + return; + + combat.setSpeedTable(); + combat._whosTurn = -1; + combat._whosSpeed = -1; + Common::fill(&combat._charsGone[0], &combat._charsGone[0] + combat._charsGone.size(), 0); + continue; + } + + if (combat._whosTurn < (int)combat._combatParty.size()) { + // It's a party character's turn now, so highlight the character + if (!combat.allHaveGone()) { + highlightChar(combat._whosTurn); + } break; + } else { + // It's a monster's turn to attack + combat.attackMonster(0); + if (!party._dead) { + party.checkPartyDead(); + if (party._dead) + break; + } + } } } -- cgit v1.2.3 From 4191335dfabc0baff9459a61e5453dad6270582f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 25 Feb 2015 22:03:57 -0500 Subject: XEEN: Method rename and compilation warning fixes --- engines/xeen/combat.cpp | 8 ++++---- engines/xeen/combat.h | 2 +- engines/xeen/interface.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index c3590e7cdd..1aa41fb52b 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -621,7 +621,7 @@ void Combat::monstersAttack() { for (int idx = 0; idx < 36; ++idx) { if (_gmonHit[idx] != -1) - attackMonster(_gmonHit[idx]); + doMonsterTurn(_gmonHit[idx]); } _monstersAttacking = false; @@ -770,7 +770,7 @@ void Combat::monsterOvercome() { } } -void Combat::attackMonster(int monsterId) { +void Combat::doMonsterTurn(int monsterId) { Interface &intf = *_vm->_interface; Map &map = *_vm->_map; Party &party = *_vm->_party; @@ -808,7 +808,7 @@ void Combat::attackMonster(int monsterId) { intf.draw3d(true); intf.draw3d(true); - File f(monsterData._attackVoc); + File f(Common::String::format("%s.voc", monsterData._attackVoc.c_str())); sound.playSample(&f, 0); bool flag = false; @@ -1073,7 +1073,7 @@ void Combat::setupCombatParty() { void Combat::setSpeedTable() { Map &map = *_vm->_map; Common::Array<int> charSpeeds; - bool hasSpeed = _whosSpeed != -1 && _whosSpeed < _speedTable.size(); + bool hasSpeed = _whosSpeed != -1 && _whosSpeed < (int)_speedTable.size(); int oldSpeed = hasSpeed ? _speedTable[_whosSpeed] : 0; // Set up speeds for party membres diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index d4cb87ea39..4783819c70 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -158,7 +158,7 @@ public: void moveMonster(int monsterId, const Common::Point &moveDelta); - void attackMonster(int monsterId); + void doMonsterTurn(int monsterId); void endAttack(); diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 74749d4f9a..c06ef79dc9 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -2218,7 +2218,7 @@ void Interface::nextChar() { break; } else { // It's a monster's turn to attack - combat.attackMonster(0); + combat.doMonsterTurn(0); if (!party._dead) { party.checkPartyDead(); if (party._dead) -- cgit v1.2.3 From 68e30b2967797537a951c5126b89fdb905138cb6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 26 Feb 2015 08:10:01 -0500 Subject: XEEN: Fix monster/party taking turns in combat --- engines/xeen/combat.cpp | 65 +++++++++++++++++++++++----------------------- engines/xeen/interface.cpp | 4 ++- 2 files changed, 35 insertions(+), 34 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 1aa41fb52b..4e32d431a8 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -777,41 +777,40 @@ void Combat::doMonsterTurn(int monsterId) { SoundManager &sound = *_vm->_sound; if (_monstersAttacking) { - warning("TODO: Original used uninitialized variables if flag was set"); - return; - } + int monsterIndex; + switch (_whosTurn - _combatParty.size()) { + case 0: + monsterIndex = _attackMonsters[0]; + intf._indoorList[156]._scale = 0; + break; + case 1: + monsterIndex = _attackMonsters[1]; + intf._indoorList[150]._scale = 0; + break; + case 2: + default: + monsterIndex = _attackMonsters[2]; + intf._indoorList[153]._scale = 0; + } - int monsterIndex; - switch (_whosTurn - _combatParty.size()) { - case 0: - monsterIndex = _attackMonsters[0]; - intf._indoorList[156]._scale = 0; - break; - case 1: - monsterIndex = _attackMonsters[1]; - intf._indoorList[150]._scale = 0; - break; - case 2: - default: - monsterIndex = _attackMonsters[2]; - intf._indoorList[153]._scale = 0; - } + MazeMonster &monster = map._mobData._monsters[monsterIndex]; + MonsterStruct &monsterData = *monster._monsterData; + if (monster._damageType) + return; - MazeMonster &monster = map._mobData._monsters[monsterIndex]; - MonsterStruct &monsterData = *monster._monsterData; - if (monster._damageType) - return; + monster._frame = 8; + monster._fieldA = 3; + monster._field9 = 0; + intf.draw3d(true); + intf.draw3d(true); - monster._frame = 8; - monster._fieldA = 3; - monster._field9 = 0; - intf.draw3d(true); - intf.draw3d(true); + File f(Common::String::format("%s.voc", monsterData._attackVoc.c_str())); + sound.playSample(&f, 0); + monsterId = monster._spriteId; + } - File f(Common::String::format("%s.voc", monsterData._attackVoc.c_str())); - sound.playSample(&f, 0); + MonsterStruct &monsterData = map._monsterData[monsterId]; bool flag = false; - for (int attackNum = 0; attackNum < monsterData._numberOfAttacks; ++attackNum) { int charNum = -1; bool isHated = false; @@ -918,14 +917,14 @@ void Combat::doMonsterTurn(int monsterId) { if (true) { Character &c = *_combatParty[charNum]; if (monsterData._attackType != DT_PHYSICAL || c._conditions[ASLEEP]) { - doCharDamage(c, charNum, monster._spriteId); + doCharDamage(c, charNum, monsterId); } else { int v = _vm->getRandomNumber(1, 20); if (v == 1) { sound.playFX(6); } else { if (v == 20) - doCharDamage(c, charNum, monster._spriteId); + doCharDamage(c, charNum, monsterId); v += monsterData._hitChance / 4 + _vm->getRandomNumber(1, monsterData._hitChance); @@ -934,7 +933,7 @@ void Combat::doMonsterTurn(int monsterId) { if (ac > v) { sound.playFX(6); } else { - doCharDamage(c, charNum, monster._spriteId); + doCharDamage(c, charNum, monsterId); } } } diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index c06ef79dc9..6c65dd4f0b 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -2192,7 +2192,9 @@ void Interface::nextChar() { } if (combat._whosTurn < (int)combat._combatParty.size()) { - if (!combat._combatParty[idx]->isDisabledOrDead()) + // If it's a party member, only allow them to become active if + // they're still conscious + if (combat._combatParty[idx]->isDisabledOrDead()) continue; } -- cgit v1.2.3 From 19007bac4088f4933410438c242814915b20e4ac Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 26 Feb 2015 08:29:04 -0500 Subject: XEEN: Fix hang calling checkEvents when in combat mode --- engines/xeen/scripts.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 0d701fe3da..ef101b9377 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -167,7 +167,7 @@ int Scripts::checkEvents() { if (eventIndex == map._events.size()) _lineNum = -1; } - } while (!_vm->shouldQuit() && _lineNum != -1); + } while (!_vm->shouldQuit() && !_eventSkipped && _lineNum != -1); intf._face1State = intf._face2State = 2; if (_refreshIcons) { -- cgit v1.2.3 From c069a7f805b18428d095a0adf643753ceeaa59e3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 26 Feb 2015 19:58:05 -0500 Subject: XEEN: Fix mode change across display of CastSpell dialog --- engines/xeen/dialogs_spells.cpp | 17 +++++++++-------- engines/xeen/dialogs_spells.h | 6 +++--- engines/xeen/interface.cpp | 7 +++++-- 3 files changed, 17 insertions(+), 13 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index ea423aac72..9a19ac2042 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -435,7 +435,7 @@ const char *SpellsDialog::setSpellText(Character *c, int isCasting) { /*------------------------------------------------------------------------*/ -int CastSpell::show(XeenEngine *vm, int mode) { +int CastSpell::show(XeenEngine *vm) { Combat &combat = *vm->_combat; Interface &intf = *vm->_interface; Party &party = *vm->_party; @@ -443,7 +443,7 @@ int CastSpell::show(XeenEngine *vm, int mode) { int charNum; // Get which character is doing the casting - if (mode == MODE_COMBAT) { + if (vm->_mode == MODE_COMBAT) { charNum = combat._whosTurn; } else if (spells._lastCaster >= 0 && spells._lastCaster < (int)party._activeParty.size()) { charNum = spells._lastCaster; @@ -460,21 +460,21 @@ int CastSpell::show(XeenEngine *vm, int mode) { intf.highlightChar(charNum); CastSpell *dlg = new CastSpell(vm); - int spellId = dlg->execute(c, mode); + int spellId = dlg->execute(c); delete dlg; return spellId; } -int CastSpell::show(XeenEngine *vm, Character *&c, int mode) { +int CastSpell::show(XeenEngine *vm, Character *&c) { CastSpell *dlg = new CastSpell(vm); - int spellId = dlg->execute(c, mode); + int spellId = dlg->execute(c); delete dlg; return spellId; } -int CastSpell::execute(Character *&c, int mode) { +int CastSpell::execute(Character *&c) { EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; Party &party = *_vm->_party; @@ -482,7 +482,8 @@ int CastSpell::execute(Character *&c, int mode) { Spells &spells = *_vm->_spells; Window &w = screen._windows[10]; - Mode oldMode = (Mode)mode; + Mode oldMode = _vm->_mode; + _vm->_mode = MODE_3; w.open(); loadButtons(); @@ -503,7 +504,6 @@ int CastSpell::execute(Character *&c, int mode) { drawButtons(&screen); w.update(); - _vm->_mode = MODE_3; redrawFlag = false; } @@ -565,6 +565,7 @@ int CastSpell::execute(Character *&c, int mode) { if (_vm->shouldQuit()) spellId = -1; + _vm->_mode = oldMode; return spellId; } diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h index 32d079023d..6a9e43f416 100644 --- a/engines/xeen/dialogs_spells.h +++ b/engines/xeen/dialogs_spells.h @@ -65,12 +65,12 @@ private: CastSpell(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} - int execute(Character *&c, int mode); + int execute(Character *&c); void loadButtons(); public: - static int show(XeenEngine *vm, int mode); - static int show(XeenEngine *vm, Character *&c, int mode); + static int show(XeenEngine *vm); + static int show(XeenEngine *vm, Character *&c); }; } // End of namespace Xeen diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 6c65dd4f0b..076437add6 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -531,7 +531,7 @@ void Interface::perform() { spells._lastCaster >= (int)party._activeParty.size()) ? (int)party._activeParty.size() - 1 : spells._lastCaster]; do { - int spellId = CastSpell::show(_vm, c, _vm->_mode); + int spellId = CastSpell::show(_vm, c); if (spellId == -1 || c == nullptr) break; @@ -1975,10 +1975,13 @@ void Interface::doCombat() { case Common::KEYCODE_c: { // Cast spell - int spellId = CastSpell::show(_vm, _vm->_mode); + int spellId = CastSpell::show(_vm); if (spellId != -1) { Character *c = combat._combatParty[combat._whosTurn]; spells.castSpell(c, spellId); + nextChar(); + } else { + highlightChar(combat._combatParty[combat._whosTurn]->_rosterId); } break; } -- cgit v1.2.3 From dc7e4153d4fb7de1d8e2241fe9b836e4680cf650 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 26 Feb 2015 20:50:49 -0500 Subject: XEEN: Fixes for attacking monsters --- engines/xeen/combat.cpp | 10 +++++----- engines/xeen/combat.h | 2 +- engines/xeen/interface.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 4e32d431a8..fca7fcb3ee 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -1342,11 +1342,11 @@ void Combat::attack(Character &c, RangeType rangeType) { break; } - int numberOfAttacks = c.getCurrentLevel() / divisor; + int numberOfAttacks = c.getCurrentLevel() / divisor + 1; damage = 0; while (numberOfAttacks-- > 0) { - if (hitMonster(c, RT_0)) + if (hitMonster(c, RT_CLOSE)) damage += getMonsterDamage(c); } @@ -1593,7 +1593,7 @@ void Combat::quickFight() { switch (c->_quickOption) { case QUICK_ATTACK: - attack(*c, RT_0); + attack(*c, RT_CLOSE); break; case QUICK_SPELL: if (c->_currentSpell != -1) { @@ -1720,7 +1720,7 @@ void Combat::getWeaponDamage(Character &c, RangeType rangeType) { } int Combat::getMonsterDamage(Character &c) { - return (c.statBonus(c.getStat(MIGHT)) + _weaponDamage) < 1; + return MAX(c.statBonus(c.getStat(MIGHT)) + _weaponDamage, 1); } int Combat::getDamageScale(int v) { @@ -1739,7 +1739,7 @@ int Combat::getMonsterResistence(RangeType rangeType) { MonsterStruct &monsterData = *monster._monsterData; int resistence = 0, damage = 0; - if (rangeType != RT_0 && rangeType != RT_3) { + if (rangeType != RT_CLOSE && rangeType != RT_3) { switch (_damageType) { case DT_PHYSICAL: resistence = monsterData._phsyicalResistence; diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 4783819c70..bf35ca819d 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -57,7 +57,7 @@ enum ElementalCategory { }; enum RangeType { - RT_0 = 0, RT_1 = 1, RT_2 = 2, RT_3 = 3 + RT_CLOSE = 0, RT_1 = 1, RT_2 = 2, RT_3 = 3 }; class XeenEngine; diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 076437add6..01cd494eff 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -1963,7 +1963,7 @@ void Interface::doCombat() { case Common::KEYCODE_a: // Attack - combat.attack(*combat._combatParty[combat._whosTurn], RT_0); + combat.attack(*combat._combatParty[combat._whosTurn], RT_CLOSE); nextChar(); break; -- cgit v1.2.3 From 349ad82f93f44f521c8023dd88e962d4835be98b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 26 Feb 2015 21:35:45 -0500 Subject: XEEN: Fix moving backwards --- engines/xeen/interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 01cd494eff..de4137ebd6 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -920,7 +920,7 @@ bool Interface::checkMoveDirection(int key) { (Direction)(party._mazeDirection + 1); break; case Common::KEYCODE_DOWN: - party._mazeDirection = (party._mazeDirection == DIR_NORTH) ? DIR_SOUTH : DIR_NORTH; + party._mazeDirection = (Direction)((int)party._mazeDirection ^ 2); break; default: break; -- cgit v1.2.3 From b46561ef293da3299ff4e7fb85ffd49222faab67 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 27 Feb 2015 07:50:32 -0500 Subject: XEEN: Implemented openGrate --- engines/xeen/dialogs_whowill.cpp | 5 ++-- engines/xeen/interface.cpp | 10 ++++--- engines/xeen/resources.cpp | 8 +++--- engines/xeen/scripts.cpp | 61 ++++++++++++++++++++++++++++++++++++---- engines/xeen/scripts.h | 4 +-- engines/xeen/xeen.cpp | 2 +- 6 files changed, 70 insertions(+), 20 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_whowill.cpp b/engines/xeen/dialogs_whowill.cpp index 10bbae26ee..fd72154cba 100644 --- a/engines/xeen/dialogs_whowill.cpp +++ b/engines/xeen/dialogs_whowill.cpp @@ -84,8 +84,8 @@ int WhoWill::execute(int message, int action, bool type) { if (_buttonValue == 27) { _buttonValue = 0; break; - } else if (_buttonValue >= 201 && _buttonValue <= 206) { - _buttonValue -= 201; + } else if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) { + _buttonValue -= Common::KEYCODE_F1 - 1; if (_buttonValue > (int)party._activeParty.size()) continue; @@ -97,7 +97,6 @@ int WhoWill::execute(int message, int action, bool type) { } } - intf._face1State = intf._face2State = 2; screen._windows[36].close(); return _buttonValue; diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index de4137ebd6..ded3d9ca00 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -269,22 +269,24 @@ void Interface::perform() { Party &party = *_vm->_party; Scripts &scripts = *_vm->_scripts; Spells &spells = *_vm->_spells; - const Common::Rect waitBounds(8, 8, 224, 140); + const Common::Rect WAIT_BOUNDS(8, 8, 224, 140); events.updateGameCounter(); draw3d(true); - // Wait for a frame + // Wait for a frame or a user event do { events.pollEventsAndWait(); checkEvents(_vm); + + if (events._leftButton && WAIT_BOUNDS.contains(events._mousePos)) + _buttonValue = Common::KEYCODE_SPACE; } while (!_buttonValue && events.timeElapsed() < 1 && !_vm->_party->_partyDead); if (!_buttonValue && !_vm->_party->_partyDead) return; - if (_buttonValue == Common::KEYCODE_SPACE || - (events._leftButton && waitBounds.contains(events._mousePos))) { + if (_buttonValue == Common::KEYCODE_SPACE) { int lookupId = map.mazeLookup(party._mazePosition, WALL_SHIFTS[party._mazeDirection][2]); diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 2716f245b3..5c76d29173 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -107,10 +107,10 @@ const char *const SURFACE_NAMES[16] = { }; const char *const WHO_ACTIONS[32] = { - "aSearch", "aOpen", "aDrink", "aMine", "aTouch", "aRead", "aLearn", "aTake", - "aBang", "aSteal", "aBribe", "aPay", "aSit", "aTry", "aTurn", "aBathe", - "aDestroy", "aPull", "aDescend", "aTossACoin", "aPray", "aJoin", "aAct", - "aPlay", "aPush", "aRub", "aPick", "aEat", "aSign", "aClose", "aLook", "aTry" + "search", "open", "drink", "mine", "touch", "read", "learn", "take", + "bang", "steal", "bribe", "pay", "sit", "try", "turn", "bathe", + "destroy", "pull", "descend", "toss a coin", "pray", "join", "act", + "play", "push", "rub", "pick", "eat", "sign", "close", "look", "try" }; const char *const WHO_WILL_ACTIONS[4] = { diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index ef101b9377..f1bce0438c 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -207,12 +207,63 @@ int Scripts::checkEvents() { return _scriptResult; } -void Scripts::giveTreasure() { - // TODO -} +void Scripts::openGrate(int wallVal, int action) { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + bool isDarkCc = _vm->_files->_isDarkCc; + + if ((wallVal != 13 || map._currentIsGrate) && (!isDarkCc || wallVal != 9 || + map.mazeData()._wallKind != 2)) { + if (wallVal != 9 && !map._currentIsGrate) { + int charIndex = WhoWill::show(_vm, 13, action, false) - 1; + if (charIndex >= 0) { + // There is a 1 in 4 chance the character will receive damage + if (_vm->getRandomNumber(1, 4) == 1) { + combat.giveCharDamage(map.mazeData()._trapDamage, + (DamageType)_vm->getRandomNumber(0, 6), charIndex); + } -void Scripts::openGrate(int v1, int v2) { - // TODO + // Check whether character can unlock the door + Character &c = party._activeParty[charIndex]; + if ((c.getThievery() + _vm->getRandomNumber(1, 20)) < + map.mazeData()._difficulties._unlockDoor) + return; + + c._experience += map.mazeData()._difficulties._unlockDoor * c.getCurrentLevel(); + } + + // Set the wall state for the wall party is facing + map.setCellSurfaceFlags(party._mazePosition, 0x80); + map.setWall(party._mazePosition, party._mazeDirection, wallVal); + + // Set the wall state for the reverse wall in the next cell over + Common::Point pt = party._mazePosition; + Direction dir = (Direction)((int)party._mazeDirection ^ 2); + switch (party._mazeDirection) { + case DIR_NORTH: + pt.y++; + break; + case DIR_EAST: + pt.x++; + break; + case DIR_SOUTH: + pt.y--; + break; + case DIR_WEST: + pt.x--; + break; + } + + map.setCellSurfaceFlags(pt, 0x80); + map.setWall(pt, dir, wallVal); + sound.playFX(10); + } + + intf.draw3d(true); + } } typedef void(Scripts::*ScriptMethodPtr)(Common::Array<byte> &); diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 1db672bd18..d347ec07bf 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -233,9 +233,7 @@ public: int checkEvents(); - void giveTreasure(); - - void openGrate(int v1, int v2); + void openGrate(int v1, int action); }; } // End of namespace Xeen diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 1410d65627..a1604a5eab 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -333,7 +333,7 @@ void XeenEngine::gameLoop() { if (shouldQuit() || _quitMode) return; } - _scripts->giveTreasure(); + _party->giveTreasure(); // Main user interface handler for waiting for and processing user input _interface->perform(); -- cgit v1.2.3 From b9539c6cb168ecabda994353a453e050b380487f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 27 Feb 2015 20:52:59 -0500 Subject: XEEN: Fixes for marking grates as unlocked --- engines/xeen/interface.cpp | 2 ++ engines/xeen/map.cpp | 11 ++++--- engines/xeen/map.h | 2 +- engines/xeen/scripts.cpp | 79 ++++++++++++++++++++++++---------------------- engines/xeen/scripts.h | 2 +- 5 files changed, 52 insertions(+), 44 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index ded3d9ca00..0354732b2b 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -299,12 +299,14 @@ void Interface::perform() { } case 6: + // Open grate being closed if (!map._isOutdoors) { scripts.openGrate(9, 0); eventsFlag = _buttonValue != 0; } break; case 9: + // Closed grate being opened if (!map._isOutdoors) { scripts.openGrate(6, 0); eventsFlag = _buttonValue != 0; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 2017978398..e5a5531cbf 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -891,7 +891,7 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) { _currentSurfaceId = 0; _currentWall = 0; _currentTile = 0; - _currentIsGrate = false; + _currentGrateUnlocked = false; _currentCantRest = false; _currentIsDrain = false; _currentIsEvent = false; @@ -1383,7 +1383,7 @@ void Map::cellFlagLookup(const Common::Point &pt) { // Get the cell flags const MazeCell &cell = _mazeData[_mazeDataIndex]._cells[pos.y][pos.x]; - _currentIsGrate = cell._flags & OUTFLAG_GRATE; + _currentGrateUnlocked = cell._flags & OUTFLAG_GRATE; _currentCantRest = cell._flags & RESTRICTION_REST; _currentIsDrain = cell._flags & OUTFLAG_DRAIN; _currentIsEvent = cell._flags & FLAG_AUTOEXECUTE_EVENT; @@ -1393,14 +1393,17 @@ void Map::cellFlagLookup(const Common::Point &pt) { void Map::setCellSurfaceFlags(const Common::Point &pt, int bits) { mazeLookup(pt, 0); - _mazeData[0]._cells[pt.y][pt.x]._surfaceId |= bits; + + Common::Point mapPos(pt.x & 15, pt.y & 15); + _mazeData[_mazeDataIndex]._cells[mapPos.y][mapPos.x]._surfaceId |= bits; } void Map::setWall(const Common::Point &pt, Direction dir, int v) { const int XOR_MASKS[4] = { 0xFFF, 0xF0FF, 0xFF0F, 0xFFF0 }; mazeLookup(pt, 0, 0); - MazeWallLayers &wallLayer = _mazeData[0]._wallData[pt.y][pt.x]; + Common::Point mapPos(pt.x & 15, pt.y & 15); + MazeWallLayers &wallLayer = _mazeData[_mazeDataIndex]._wallData[mapPos.y][mapPos.x]; wallLayer._data &= XOR_MASKS[dir]; wallLayer._data |= v << WALL_SHIFTS[dir][2]; } diff --git a/engines/xeen/map.h b/engines/xeen/map.h index bd74837788..bfc09ec053 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -376,7 +376,7 @@ public: SpriteResource _tileSprites; SpriteResource _surfaceSprites[TOTAL_SURFACES]; WallSprites _wallSprites; - bool _currentIsGrate; + bool _currentGrateUnlocked; bool _currentCantRest; bool _currentIsDrain; bool _currentIsEvent; diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index f1bce0438c..4af7af1d6a 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -215,53 +215,56 @@ void Scripts::openGrate(int wallVal, int action) { SoundManager &sound = *_vm->_sound; bool isDarkCc = _vm->_files->_isDarkCc; - if ((wallVal != 13 || map._currentIsGrate) && (!isDarkCc || wallVal != 9 || + if ((wallVal != 13 || map._currentGrateUnlocked) && (!isDarkCc || wallVal != 9 || map.mazeData()._wallKind != 2)) { - if (wallVal != 9 && !map._currentIsGrate) { + if (wallVal != 9 && !map._currentGrateUnlocked) { int charIndex = WhoWill::show(_vm, 13, action, false) - 1; - if (charIndex >= 0) { - // There is a 1 in 4 chance the character will receive damage - if (_vm->getRandomNumber(1, 4) == 1) { - combat.giveCharDamage(map.mazeData()._trapDamage, - (DamageType)_vm->getRandomNumber(0, 6), charIndex); - } - - // Check whether character can unlock the door - Character &c = party._activeParty[charIndex]; - if ((c.getThievery() + _vm->getRandomNumber(1, 20)) < - map.mazeData()._difficulties._unlockDoor) - return; + if (charIndex < 0) { + intf.draw3d(true); + return; + } - c._experience += map.mazeData()._difficulties._unlockDoor * c.getCurrentLevel(); + // There is a 1 in 4 chance the character will receive damage + if (_vm->getRandomNumber(1, 4) == 1) { + combat.giveCharDamage(map.mazeData()._trapDamage, + (DamageType)_vm->getRandomNumber(0, 6), charIndex); } - // Set the wall state for the wall party is facing - map.setCellSurfaceFlags(party._mazePosition, 0x80); - map.setWall(party._mazePosition, party._mazeDirection, wallVal); + // Check whether character can unlock the door + Character &c = party._activeParty[charIndex]; + if ((c.getThievery() + _vm->getRandomNumber(1, 20)) < + map.mazeData()._difficulties._unlockDoor) + return; - // Set the wall state for the reverse wall in the next cell over - Common::Point pt = party._mazePosition; - Direction dir = (Direction)((int)party._mazeDirection ^ 2); - switch (party._mazeDirection) { - case DIR_NORTH: - pt.y++; - break; - case DIR_EAST: - pt.x++; - break; - case DIR_SOUTH: - pt.y--; - break; - case DIR_WEST: - pt.x--; - break; - } + c._experience += map.mazeData()._difficulties._unlockDoor * c.getCurrentLevel(); + } + + // Flag the grate as unlocked, and the wall the grate is on + map.setCellSurfaceFlags(party._mazePosition, 0x80); + map.setWall(party._mazePosition, party._mazeDirection, wallVal); - map.setCellSurfaceFlags(pt, 0x80); - map.setWall(pt, dir, wallVal); - sound.playFX(10); + // Set the grate as opened and the wall on the other side of the grate + Common::Point pt = party._mazePosition; + Direction dir = (Direction)((int)party._mazeDirection ^ 2); + switch (party._mazeDirection) { + case DIR_NORTH: + pt.y++; + break; + case DIR_EAST: + pt.x++; + break; + case DIR_SOUTH: + pt.y--; + break; + case DIR_WEST: + pt.x--; + break; } + map.setCellSurfaceFlags(pt, 0x80); + map.setWall(pt, dir, wallVal); + + sound.playFX(10); intf.draw3d(true); } } diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index d347ec07bf..3a835d88b5 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -233,7 +233,7 @@ public: int checkEvents(); - void openGrate(int v1, int action); + void openGrate(int wallVal, int action); }; } // End of namespace Xeen -- cgit v1.2.3 From 302b3cdc63fe24b4c702c260935879fd7f477bd5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 27 Feb 2015 21:33:07 -0500 Subject: XEEN: Fix updating cell flag that grate is unlocked --- engines/xeen/map.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index e5a5531cbf..021c417528 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1395,7 +1395,8 @@ void Map::setCellSurfaceFlags(const Common::Point &pt, int bits) { mazeLookup(pt, 0); Common::Point mapPos(pt.x & 15, pt.y & 15); - _mazeData[_mazeDataIndex]._cells[mapPos.y][mapPos.x]._surfaceId |= bits; + MazeCell &cell = _mazeData[_mazeDataIndex]._cells[mapPos.y][mapPos.x]; + cell._flags |= bits & 0xF8; } void Map::setWall(const Common::Point &pt, Direction dir, int v) { @@ -1453,7 +1454,7 @@ int Map::getCell(int idx) { if (_vm->_files->_isDarkCc) { if ((mapId >= 53 && mapId <= 88 && mapId != 73) || (mapId >= 74 && mapId <= 120) || mapId == 125 || mapId == 126 || mapId == 128 || mapId == 129) { - _currentSurfaceId = SURFTYPE_DESERT; + _currentSurfaceId = 6; } else { _currentSurfaceId = 0; } @@ -1489,7 +1490,7 @@ int Map::getCell(int idx) { if (_vm->_files->_isDarkCc) { if ((mapId >= 53 && mapId <= 88 && mapId != 73) || (mapId >= 74 && mapId <= 120) || mapId == 125 || mapId == 126 || mapId == 128 || mapId == 129) { - _currentSurfaceId = SURFTYPE_DESERT; + _currentSurfaceId = 6; } else { _currentSurfaceId = 0; } @@ -1524,7 +1525,7 @@ int Map::getCell(int idx) { return 0; if (pt.x > 31 || pt.y > 31) - _currentSurfaceId = SURFTYPE_ROAD; + _currentSurfaceId = 7; else _currentSurfaceId = _mazeData[_mazeDataIndex]._cells[pt.y][pt.x]._surfaceId; -- cgit v1.2.3 From 973c5a0df5bf9f86cc589a7a138899b96684bf23 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 28 Feb 2015 12:45:33 -0500 Subject: XEEN: Implemented multiAttack --- engines/xeen/character.cpp | 10 ++ engines/xeen/character.h | 2 + engines/xeen/combat.cpp | 276 +++++++++++++++++++++++++++++++++++++++++++-- engines/xeen/combat.h | 13 ++- engines/xeen/interface.cpp | 2 +- engines/xeen/spells.cpp | 37 +++++- 6 files changed, 324 insertions(+), 16 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index e005a35f13..d95e061515 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -1848,6 +1848,16 @@ bool Character::hasSpecialItem() const { return false; } +bool Character::hasMissileWeapon() const { + for (uint idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + if (_weapons[idx]._frame == 4) { + return !isDisabledOrDead(); + } + } + + return false; +} + int Character::getClassCategory() const { switch (_class) { case CLASS_ARCHER: diff --git a/engines/xeen/character.h b/engines/xeen/character.h index 9e858da7fa..77ab882305 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -326,6 +326,8 @@ public: bool hasSpecialItem() const; + bool hasMissileWeapon() const; + int getClassCategory() const; }; diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index fca7fcb3ee..763daa7d03 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -116,7 +116,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.vo _whosSpeed = 0; _damageType = DT_PHYSICAL; _oldCharacter = nullptr; - _shootType = 0; + _shootType = ST_0; _monsterDamage = 0; _weaponDamage = 0; _weaponDie = _weaponDice = 0; @@ -125,6 +125,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.vo _hitChanceBonus = 0; _dangerPresent = false; _moveMonsters = false; + _rangeType = RT_SINGLE; } void Combat::clear() { @@ -1198,7 +1199,7 @@ void Combat::attack(Character &c, RangeType rangeType) { MonsterStruct &monsterData = map._monsterData[monsterDataIndex]; if (rangeType) { - if (_shootType != 1 || _damageType == DT_MAGIC_ARROW) { + if (_shootType != ST_1 || _damageType == DT_MAGIC_ARROW) { if (!monsterData._magicResistence || monsterData._magicResistence <= _vm->getRandomNumber(1, 100 + _oldCharacter->getCurrentLevel())) { if (_monsterDamage != 0) { @@ -1216,25 +1217,25 @@ void Combat::attack(Character &c, RangeType rangeType) { if ((monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID) && !monsterSavingThrow(monsterDataIndex)) { damage = MIN(monster._hp, 50); - attack2(damage, RT_2); + attack2(damage, RT_ALL); setSpeedTable(); } break; case DT_HOLYWORD: if (monsterData._monsterType == MONSTER_UNDEAD) { - attack2(monster._hp, RT_2); + attack2(monster._hp, RT_ALL); setSpeedTable(); } break; case DT_MASS_DISTORTION: - attack2(MAX(monster._hp / 2, 1), RT_2); + attack2(MAX(monster._hp / 2, 1), RT_ALL); setSpeedTable(); break; case DT_UNDEAD: if (monsterData._monsterType == MONSTER_UNDEAD) damage = 25; else - rangeType = RT_2; + rangeType = RT_ALL; attack2(damage, rangeType); setSpeedTable(); break; @@ -1346,7 +1347,7 @@ void Combat::attack(Character &c, RangeType rangeType) { damage = 0; while (numberOfAttacks-- > 0) { - if (hitMonster(c, RT_CLOSE)) + if (hitMonster(c, RT_SINGLE)) damage += getMonsterDamage(c); } @@ -1593,7 +1594,7 @@ void Combat::quickFight() { switch (c->_quickOption) { case QUICK_ATTACK: - attack(*c, RT_CLOSE); + attack(*c, RT_SINGLE); break; case QUICK_SPELL: if (c->_currentSpell != -1) { @@ -1739,7 +1740,7 @@ int Combat::getMonsterResistence(RangeType rangeType) { MonsterStruct &monsterData = *monster._monsterData; int resistence = 0, damage = 0; - if (rangeType != RT_CLOSE && rangeType != RT_3) { + if (rangeType != RT_SINGLE && rangeType != RT_3) { switch (_damageType) { case DT_PHYSICAL: resistence = monsterData._phsyicalResistence; @@ -1825,4 +1826,261 @@ void Combat::giveExperience(int experience) { } } +void Combat::multiAttack(int powNum) { + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + if (_damageType == DT_POISON_VOLLEY) { + _damageType = DT_POISON; + _shootType = ST_1; + Common::fill(&_shooting[0], &_shooting[6], 1); + } else if (powNum == 11) { + _shootType = ST_1; + bool flag = false; + + if (_damageType == DT_PHYSICAL) { + for (uint idx = 0; idx < party._activeParty.size(); ++idx) { + Character &c = party._activeParty[idx]; + if (c.hasMissileWeapon()) { + _shooting[idx] = 1; + flag = true; + } + } + } else { + _shooting[0] = 1; + flag = true; + } + + if (!flag) { + sound.playFX(21); + return; + } + } else { + _shooting[0] = 1; + _shootType = ST_0; + } + + intf._charsShooting = true; + _powSprites.load(Common::String::format("pow%d.icn", powNum)); + int monsterIndex = _monsterIndex; + int monster2Attack = _monster2Attack; + bool attackedFlag = false; + + Common::Array<int> attackMonsters; + for (int idx = 0; idx < 3; ++idx) { + if (_attackMonsters[idx] != -1) + attackMonsters.push_back(_attackMonsters[idx]); + } + + _monsterIndex = -1; + if (_monster2Attack != -1) { + _monsterIndex--; + if (attackMonsters.empty()) + attackMonsters.resize(1); + attackMonsters[0] = monster2Attack; + } + + for (uint idx = 0; idx < party._activeParty.size(); ++idx) { + Character &c = party._activeParty[idx]; + if (_shooting[idx]) { + if (map._isOutdoors) { + intf._outdoorList._attackImgs1[idx]._scale = 0; + intf._outdoorList._attackImgs2[idx]._scale = 4; + intf._outdoorList._attackImgs3[idx]._scale = 8; + intf._outdoorList._attackImgs4[idx]._scale = 12; + intf._outdoorList._attackImgs1[idx]._sprites = &_powSprites; + intf._outdoorList._attackImgs2[idx]._sprites = nullptr; + intf._outdoorList._attackImgs3[idx]._sprites = nullptr; + intf._outdoorList._attackImgs4[idx]._sprites = nullptr; + } else { + intf._indoorList._attackImgs1[idx]._scale = 0; + intf._indoorList._attackImgs2[idx]._scale = 4; + intf._indoorList._attackImgs3[idx]._scale = 8; + intf._indoorList._attackImgs4[idx]._scale = 12; + intf._indoorList._attackImgs1[idx]._sprites = &_powSprites; + intf._indoorList._attackImgs2[idx]._sprites = nullptr; + intf._indoorList._attackImgs3[idx]._sprites = nullptr; + intf._indoorList._attackImgs4[idx]._sprites = nullptr; + } + } + } + + intf.draw3d(true); + + ++_monsterIndex; + for (uint monIdx = 0; monIdx < attackMonsters.size(); ++monIdx, ++_monsterIndex) { + Common::fill(&_missedShot[0], &_missedShot[8], false); + _monster2Attack = attackMonsters[monIdx]; + attack(*_oldCharacter, RT_GROUP); + attackedFlag = true; + + if (_rangeType == RT_SINGLE) + // Only single shot, so exit now that the attack is done + goto finished; + } + + if (attackedFlag && _rangeType == RT_GROUP) + // Finished group attack, so exit + goto finished; + + if (map._isOutdoors) { + map.getCell(7); + switch (map._currentWall) { + case 1: + case 3: + case 6: + case 7: + case 9: + case 10: + case 12: + sound.playFX(46); + goto finished; + default: + break; + } + } else { + int cell = map.getCell(2); + if (cell < map.mazeData()._difficulties._wallNoPass) { + sound.playFX(46); + goto finished; + } + } + if (!intf._isAttacking) + goto finished; + + intf.draw3d(true); + + // Start handling second teir of monsters in the back + attackMonsters.clear(); + for (uint idx = 3; idx < 6; ++idx) { + if (_attackMonsters[idx] != -1) + attackMonsters.push_back(_attackMonsters[idx]); + } + + ++_monsterIndex; + for (uint monIdx = 0; monIdx < attackMonsters.size(); ++monIdx, ++_monsterIndex) { + Common::fill(&_missedShot[0], &_missedShot[8], false); + _monster2Attack = attackMonsters[monIdx]; + attack(*_oldCharacter, RT_GROUP); + attackedFlag = true; + + if (_rangeType == RT_SINGLE) + // Only single shot, so exit now that the attack is done + goto finished; + } + + if (attackedFlag && _rangeType == RT_GROUP) + // Finished group attack, so exit + goto finished; + + if (map._isOutdoors) { + map.getCell(14); + switch (map._currentWall) { + case 1: + case 3: + case 6: + case 7: + case 9: + case 10: + case 12: + sound.playFX(46); + goto finished; + default: + break; + } + } else { + int cell = map.getCell(7); + if (cell < map.mazeData()._difficulties._wallNoPass) { + sound.playFX(46); + goto finished; + } + } + if (!intf._isAttacking) + goto finished; + + intf.draw3d(true); + + // Start handling third teir of monsters in the back + attackMonsters.clear(); + for (uint idx = 6; idx < 9; ++idx) { + if (_attackMonsters[idx] != -1) + attackMonsters.push_back(_attackMonsters[idx]); + } + + ++_monsterIndex; + for (uint monIdx = 0; monIdx < attackMonsters.size(); ++monIdx, ++_monsterIndex) { + Common::fill(&_missedShot[0], &_missedShot[8], false); + _monster2Attack = attackMonsters[monIdx]; + attack(*_oldCharacter, RT_GROUP); + attackedFlag = true; + + if (_rangeType == RT_SINGLE) + // Only single shot, so exit now that the attack is done + goto finished; + } + + if (attackedFlag && _rangeType == RT_GROUP) + // Finished group attack, so exit + goto finished; + + if (map._isOutdoors) { + map.getCell(27); + switch (map._currentWall) { + case 1: + case 3: + case 6: + case 7: + case 9: + case 10: + case 12: + sound.playFX(46); + goto finished; + default: + break; + } + } else { + int cell = map.getCell(14); + if (cell < map.mazeData()._difficulties._wallNoPass) { + sound.playFX(46); + goto finished; + } + } + if (!intf._isAttacking) + goto finished; + + intf.draw3d(true); + + // Fourth tier + attackMonsters.clear(); + for (uint idx = 9; idx < 12; ++idx) { + if (_attackMonsters[idx] != -1) + attackMonsters.push_back(_attackMonsters[idx]); + } + + ++_monsterIndex; + for (uint monIdx = 0; monIdx < attackMonsters.size(); ++monIdx, ++_monsterIndex) { + Common::fill(&_missedShot[0], &_missedShot[8], false); + _monster2Attack = attackMonsters[monIdx]; + attack(*_oldCharacter, RT_GROUP); + attackedFlag = true; + + if (_rangeType == RT_SINGLE) + // Only single shot, so exit now that the attack is done + goto finished; + } + + if (!(attackedFlag && _rangeType == RT_GROUP)) + goto done; + +finished: + endAttack(); +done: + Common::fill(&_shooting[0], &_shooting[MAX_PARTY_COUNT], 0); + _monster2Attack = monster2Attack; + _monsterIndex = monsterIndex; + party.giveTreasure(); +} + } // End of namespace Xeen diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index bf35ca819d..9831f90f25 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -39,7 +39,7 @@ enum DamageType { DT_FINGEROFDEATH = 8, DT_HOLYWORD = 9, DT_MASS_DISTORTION = 10, DT_UNDEAD = 11, DT_BEASTMASTER = 12, DT_DRAGONSLEEP = 13, DT_GOLEMSTOPPER = 14, DT_HYPNOTIZE = 15, DT_INSECT_SPRAY = 16, - DT_POISON_VALLEY = 17, DT_MAGIC_ARROW = 18 + DT_POISON_VOLLEY = 17, DT_MAGIC_ARROW = 18 }; enum SpecialAttack { @@ -57,7 +57,11 @@ enum ElementalCategory { }; enum RangeType { - RT_CLOSE = 0, RT_1 = 1, RT_2 = 2, RT_3 = 3 + RT_SINGLE = 0, RT_GROUP = 1, RT_ALL = 2, RT_3 = 3 +}; + +enum ShootType { + ST_0 = 0, ST_1 = 1 }; class XeenEngine; @@ -110,7 +114,6 @@ public: int _whosSpeed; DamageType _damageType; Character *_oldCharacter; - int _shootType; int _monsterDamage; int _weaponDamage; int _weaponDie, _weaponDice; @@ -120,6 +123,8 @@ public: int _hitChanceBonus; bool _dangerPresent; bool _moveMonsters; + RangeType _rangeType; + ShootType _shootType; public: Combat(XeenEngine *vm); @@ -165,6 +170,8 @@ public: void monsterOvercome(); int stopAttack(const Common::Point &diffPt); + + void multiAttack(int powNum); }; } // End of namespace Xeen diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 0354732b2b..7339e1014f 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -1967,7 +1967,7 @@ void Interface::doCombat() { case Common::KEYCODE_a: // Attack - combat.attack(*combat._combatParty[combat._whosTurn], RT_CLOSE); + combat.attack(*combat._combatParty[combat._whosTurn], RT_SINGLE); nextChar(); break; diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 25aae11af2..53c43b5233 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -198,10 +198,41 @@ void Spells::addSpellCost(Character &c, int spellId) { party._gems += gemCost; } +void Spells::light() { + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + ++party._lightCount; + if (intf._intrIndex1) + party._stepped = true; + sound.playFX(39); +} + +void Spells::awaken() { + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + for (uint idx = 0; idx < party._activeParty.size(); ++idx) { + Character &c = party._activeParty[idx]; + c._conditions[ASLEEP] = 0; + if (c._currentHp > 0) + c._conditions[UNCONSCIOUS] = 0; + } + + intf.drawParty(true); + sound.playFX(30); +} + +void Spells::magicArrow() { + Combat &combat = *_vm->_combat; + combat._monsterDamage = 0; + combat._damageType = DT_MAGIC_ARROW; + combat._rangeType = RT_SINGLE; + combat.multiAttack(11); +} -void Spells::light() { error("TODO: spell"); } -void Spells::awaken() { error("TODO: spell"); } -void Spells::magicArrow() { error("TODO: spell"); } void Spells::firstAid() { error("TODO: spell"); } void Spells::flyingFist() { error("TODO: spell"); } void Spells::energyBlast() { error("TODO: spell"); } -- cgit v1.2.3 From b378709478fc689de8a1a0b455deb12e6aee5fb2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 28 Feb 2015 13:00:35 -0500 Subject: XEEN: Implement shoot action --- engines/xeen/combat.cpp | 9 +++++++++ engines/xeen/combat.h | 2 ++ engines/xeen/interface.cpp | 25 +++++++++++++++++++++++++ engines/xeen/party.cpp | 9 +++++++++ engines/xeen/party.h | 2 ++ 5 files changed, 47 insertions(+) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 763daa7d03..74e098cdd4 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -2083,4 +2083,13 @@ done: party.giveTreasure(); } +/** + * Fires off a ranged attack at all oncoming monsters + */ +void Combat::shootRangedWeapon() { + _rangeType = RT_ALL; + _damageType = DT_PHYSICAL; + multiAttack(11); +} + } // End of namespace Xeen diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 9831f90f25..cff9261b05 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -172,6 +172,8 @@ public: int stopAttack(const Common::Point &diffPt); void multiAttack(int powNum); + + void shootRangedWeapon(); }; } // End of namespace Xeen diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 7339e1014f..cc027b8676 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -268,6 +268,7 @@ void Interface::perform() { Map &map = *_vm->_map; Party &party = *_vm->_party; Scripts &scripts = *_vm->_scripts; + SoundManager &sound = *_vm->_sound; Spells &spells = *_vm->_spells; const Common::Rect WAIT_BOUNDS(8, 8, 224, 140); @@ -571,6 +572,30 @@ void Interface::perform() { rest(); break; + case Common::KEYCODE_s: + // Shoot + if (!party.canShoot()) { + sound.playFX(21); + } else { + if (_tillMove) { + combat.moveMonsters(); + draw3d(true); + } + + if (combat._attackMonsters[0] != -1 || combat._attackMonsters[1] != -1 + || combat._attackMonsters[2] != -1) { + if ((_vm->_mode == MODE_1 || _vm->_mode == MODE_SLEEPING) + && !combat._monstersAttacking && !_charsShooting) { + doCombat(); + } + } + + combat.shootRangedWeapon(); + chargeStep(); + doStepCode(); + } + break; + case Common::KEYCODE_v: // Show the quests dialog Quests::show(_vm); diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 268dfcce15..5e111e61b4 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -735,4 +735,13 @@ void Party::giveTreasureToCharacter(Character &c, ItemCategory category, int ite events.ipause(5); } +bool Party::canShoot() const { + for (uint idx = 0; idx < _activeParty.size(); ++idx) { + if (_activeParty[idx].hasMissileWeapon()) + return true; + } + + return false; +} + } // End of namespace Xeen diff --git a/engines/xeen/party.h b/engines/xeen/party.h index b5e31f9405..483c3f43ec 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -173,6 +173,8 @@ public: void giveTreasure(); bool arePacksFull() const; + + bool canShoot() const; }; } // End of namespace Xeen -- cgit v1.2.3 From 99aa64bda4695ca704a2902d3c6b6bd705204043 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 28 Feb 2015 14:59:43 -0500 Subject: XEEN: Fix crash on shooting --- engines/xeen/interface_map.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index de19a9957a..a9e71d4e9c 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -572,18 +572,15 @@ void InterfaceMap::drawMap() { } } } else if (_charsShooting) { - for (int idx = 0; idx < 96; ++idx) { - if (_indoorList[162 + idx]._sprites != nullptr) { - _indoorList[162 + idx]._frame = 0; - } - else if (_indoorList[135 + idx]._sprites != nullptr) { - _indoorList[135 + idx]._frame = 1; - } - else if (_indoorList[111 + idx]._sprites != nullptr) { - _indoorList[111 + idx]._frame = 2; - } - else if (_indoorList[79 + idx]._sprites != nullptr) { - _indoorList[79 + idx]._frame = 0; + for (int idx = 0; idx < 8; ++idx) { + if (_indoorList._attackImgs1[idx]._sprites != nullptr) { + _indoorList._attackImgs1[idx]._frame = 0; + } else if (_indoorList._attackImgs2[idx]._sprites != nullptr) { + _indoorList._attackImgs2[idx]._frame = 1; + } else if (_indoorList._attackImgs3[idx]._sprites != nullptr) { + _indoorList._attackImgs3[idx]._frame = 2; + } else if (_indoorList._attackImgs4[idx]._sprites != nullptr) { + _indoorList._attackImgs4[idx]._frame = 0; } } } -- cgit v1.2.3 From 93cc299eafab9e385af9b812f45809cc4645a14e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 28 Feb 2015 18:43:04 -0500 Subject: XEEN: Implement addHitPoints and spellFX methods --- engines/xeen/character.cpp | 35 +++++++++++++++++++++ engines/xeen/character.h | 4 +++ engines/xeen/combat.cpp | 3 +- engines/xeen/combat.h | 6 +++- engines/xeen/dialogs_spells.cpp | 67 +++++++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_spells.h | 11 +++++++ engines/xeen/interface.cpp | 54 +++++++++++++++++++++++++++++++-- engines/xeen/interface.h | 3 ++ engines/xeen/resources.cpp | 2 ++ engines/xeen/resources.h | 2 ++ engines/xeen/scripts.cpp | 5 ++- engines/xeen/scripts.h | 1 - engines/xeen/spells.cpp | 32 +++++++++++++++++++- engines/xeen/spells.h | 2 ++ 14 files changed, 217 insertions(+), 10 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index d95e061515..ea0f9f532e 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -875,6 +875,15 @@ bool Character::isDisabledOrDead() const { return condition == ASLEEP || (condition >= PARALYZED && condition <= ERADICATED); } +/** + * Returns whether the given character has a dead condition + */ +bool Character::isDead() const { + Condition condition = worstCondition(); + + return condition >= DEAD && condition <= ERADICATED; +} + /** * Get the character's age */ @@ -1810,6 +1819,32 @@ int Character::makeItem(int p1, int itemIndex, int p3) { return category; } +/** + * Add hit points to a character + */ +void Character::addHitPoints(int amount) { + Interface &intf = *Party::_vm->_interface; + Common::fill(&intf._charFX[0], &intf._charFX[MAX_ACTIVE_PARTY], 0); + + if (!isDead()) { + int maxHp = getMaxHP(); + if (_currentHp <= maxHp) { + _currentHp = MIN(_currentHp + amount, maxHp); + intf.spellFX(this); + } + + if (_currentHp > 0) + _conditions[UNCONSCIOUS] = 0; + + intf.drawParty(true); + } + + Common::fill(&intf._charFX[0], &intf._charFX[MAX_ACTIVE_PARTY], 0); +} + +/** + * Remove hit points fromo the character + */ void Character::subtractHitPoints(int amount) { SoundManager &sound = *Party::_vm->_sound; _currentHp -= amount; diff --git a/engines/xeen/character.h b/engines/xeen/character.h index 77ab882305..f1243f1568 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -278,6 +278,8 @@ public: bool isDisabledOrDead() const; + bool isDead() const; + int getAge(bool ignoreTemp = false) const; int getMaxHP() const; @@ -322,6 +324,8 @@ public: int makeItem(int p1, int itemIndex, int p3); + void addHitPoints(int amount); + void subtractHitPoints(int amount); bool hasSpecialItem() const; diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 74e098cdd4..7cc2ab6b22 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -109,7 +109,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.vo _whosTurn = -1; _itemFlag = false; _monstersAttacking = false; - _combatMode = 0; + _combatMode = COMBATMODE_0; _monsterIndex = 0; _partyRan = false; _monster2Attack = -1; @@ -1883,7 +1883,6 @@ void Combat::multiAttack(int powNum) { } for (uint idx = 0; idx < party._activeParty.size(); ++idx) { - Character &c = party._activeParty[idx]; if (_shooting[idx]) { if (map._isOutdoors) { intf._outdoorList._attackImgs1[idx]._scale = 0; diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index cff9261b05..33309b243b 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -64,6 +64,10 @@ enum ShootType { ST_0 = 0, ST_1 = 1 }; +enum CombatMode { + COMBATMODE_0 = 0, COMBATMODE_1 = 1, COMBATMODE_2 = 2 +}; + class XeenEngine; class Character; class XeenItem; @@ -108,7 +112,7 @@ public: bool _rangeAttacking[MAX_NUM_MONSTERS]; int _gmonHit[36]; bool _monstersAttacking; - int _combatMode; + CombatMode _combatMode; int _monsterIndex; bool _partyRan; int _whosSpeed; diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 9a19ac2042..08828a0c8d 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -577,4 +577,71 @@ void CastSpell::loadButtons() { addPartyButtons(_vm); } +/*------------------------------------------------------------------------*/ + +int SpellOnWho::show(XeenEngine *vm, int spellId) { + SpellOnWho *dlg = new SpellOnWho(vm); + int result = dlg->execute(spellId); + delete dlg; + + return result; +} + +int SpellOnWho::execute(int spellId) { + Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + Spells &spells = *_vm->_spells; + Window &w = screen._windows[16]; + Mode oldMode = _vm->_mode; + _vm->_mode = MODE_3; + int result = 999; + + w.open(); + w.writeString(ON_WHO); + w.update(); + addPartyButtons(_vm); + + while (result == 999) { + do { + events.updateGameCounter(); + intf.draw3d(true); + + do { + events.pollEventsAndWait(); + if (_vm->shouldQuit()) + return -1; + + checkEvents(_vm); + } while (!_buttonValue && events.timeElapsed() < 1); + } while (!_buttonValue); + + switch (_buttonValue) { + case Common::KEYCODE_ESCAPE: + result = -1; + spells.addSpellCost(*combat._oldCharacter, spellId); + break; + + case Common::KEYCODE_F1: + case Common::KEYCODE_F2: + case Common::KEYCODE_F3: + case Common::KEYCODE_F4: + case Common::KEYCODE_F5: + case Common::KEYCODE_F6: + _buttonValue -= Common::KEYCODE_F1; + if (_buttonValue < (int)(combat._combatMode == 2 ? combat._combatParty.size() : + party._activeParty.size())) { + result = _buttonValue; + } + break; + } + } + + w.close(); + _vm->_mode = oldMode; + return result; +} + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h index 6a9e43f416..660f2ef1de 100644 --- a/engines/xeen/dialogs_spells.h +++ b/engines/xeen/dialogs_spells.h @@ -73,6 +73,17 @@ public: static int show(XeenEngine *vm, Character *&c); }; +class SpellOnWho : public ButtonContainer { +private: + XeenEngine *_vm; + + SpellOnWho(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + int execute(int spellId); +public: + static int show(XeenEngine *vm, int spellId); +}; + } // End of namespace Xeen #endif /* XEEN_DIALOGS_SPELLS_H */ diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index cc027b8676..923eaeac0b 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -149,6 +149,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _face1State = _face2State = 0; _upDoorText = false; _tillMove = 0; + Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0); initDrawStructs(); } @@ -1891,7 +1892,7 @@ void Interface::doCombat() { bool reloadMap = false; _upDoorText = false; - combat._combatMode = 2; + combat._combatMode = COMBATMODE_2; _vm->_mode = MODE_COMBAT; _iconSprites.load("combat.icn"); @@ -2182,7 +2183,7 @@ void Interface::doCombat() { DIR_EAST : DIR_SOUTH; } - combat._combatMode = 1; + combat._combatMode = COMBATMODE_1; } /** @@ -2262,4 +2263,53 @@ void Interface::nextChar() { } } +void Interface::spellFX(Character *c) { + Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + + // Ensure there's no alraedy running effect for the given character + uint charIndex; + for (charIndex = 0; charIndex < party._activeParty.size(); ++charIndex) { + if (&party._activeParty[charIndex] == c) + break; + } + if (charIndex == party._activeParty.size() || _charFX[charIndex]) + return; + + if (screen._windows[12]._enabled) + screen._windows[12].close(); + + if (combat._combatMode == COMBATMODE_2) { + for (uint idx = 0; idx < combat._combatParty.size(); ++idx) { + if (combat._combatParty[idx]->_rosterId == c->_rosterId) { + charIndex = idx; + break; + } + } + } + + int tillMove = _tillMove; + _tillMove = 0; + sound.playFX(20); + + for (int frameNum = 0; frameNum < 4; ++frameNum) { + events.updateGameCounter(); + _spellFxSprites.draw(screen, frameNum, Common::Point( + CHAR_FACES_X[charIndex], 150)); + + if (!screen._windows[11]._enabled) + draw3d(false); + + screen._windows[0].update(); + events.wait(screen._windows[11]._enabled ? 2 : 1); + } + + drawParty(true); + _tillMove = tillMove; +} + + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index f5e5cc34ee..24edf9d23d 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -119,6 +119,7 @@ public: bool _upDoorText; Common::String _screenText; byte _tillMove; + int _charFX[6]; public: Interface(XeenEngine *vm); @@ -145,6 +146,8 @@ public: void assembleBorder(); void doCombat(); + + void spellFX(Character *c); }; } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 5c76d29173..5893403ebd 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1528,4 +1528,6 @@ const char *const GIVE_TREASURE_FORMATTING = const char *const X_FOUND_Y = "\v060\t000\x03c%s found: %s"; +const char *const ON_WHO = "\x3""c\v009On Who?"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index c98db7f0f9..b908d91cf9 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -539,6 +539,8 @@ extern const char *const GIVE_TREASURE_FORMATTING; extern const char *const X_FOUND_Y; +extern const char *const ON_WHO; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 4af7af1d6a..ec00327205 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -88,7 +88,6 @@ bool MirrorEntry::synchronize(Common::SeekableReadStream &s) { /*------------------------------------------------------------------------*/ Scripts::Scripts(XeenEngine *vm) : _vm(vm) { - Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0); _whoWill = 0; _itemType = 0; _treasureItems = 0; @@ -120,7 +119,7 @@ int Scripts::checkEvents() { _var50 = false; _whoWill = 0; Mode oldMode = _vm->_mode; - Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0); + Common::fill(&intf._charFX[0], &intf._charFX[MAX_ACTIVE_PARTY], 0); //int items = _treasureItems; if (party._treasure._gold & party._treasure._gems) { @@ -202,7 +201,7 @@ int Scripts::checkEvents() { } _v2 = 1; - Common::fill(&_charFX[0], &_charFX[6], 0); + Common::fill(&intf._charFX[0], &intf._charFX[6], 0); return _scriptResult; } diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 3a835d88b5..29de5b8b37 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -139,7 +139,6 @@ struct MirrorEntry { class Scripts { private: XeenEngine *_vm; - int _charFX[6]; int _treasureItems; int _lineNum; int _charIndex; diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 53c43b5233..d446b3ce6e 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -21,6 +21,7 @@ */ #include "xeen/spells.h" +#include "xeen/dialogs_spells.h" #include "xeen/files.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -95,6 +96,16 @@ void Spells::executeSpell(int spellId) { (this->*SPELL_LIST[spellId])(); } +/** + * Spell being cast failed + */ +void Spells::spellFailed() { + ErrorScroll::show(_vm, SPELL_FAILED, WT_NONFREEZED_WAIT); +} + +/** + * Cast a spell associated with an item + */ void Spells::castItemSpell(int spellId) { if (_vm->_mode == MODE_COMBAT) { if (spellId == 15 || spellId == 20 || spellId == 27 || spellId == 41 @@ -233,7 +244,26 @@ void Spells::magicArrow() { combat.multiAttack(11); } -void Spells::firstAid() { error("TODO: spell"); } +void Spells::firstAid() { + Combat &combat = *_vm->_combat; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + int charIndex = SpellOnWho::show(_vm, MS_FirstAid); + if (charIndex == -1) + return; + + Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : + party._activeParty[charIndex]; + + if (c.isDead()) { + spellFailed(); + } else { + sound.playFX(30); + c.addHitPoints(6); + } +} + void Spells::flyingFist() { error("TODO: spell"); } void Spells::energyBlast() { error("TODO: spell"); } void Spells::sleep() { error("TODO: spell"); } diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h index af52511efa..2f79670df0 100644 --- a/engines/xeen/spells.h +++ b/engines/xeen/spells.h @@ -69,6 +69,8 @@ private: void executeSpell(int spellId); + void spellFailed(); + // Spell list void light(); void awaken(); -- cgit v1.2.3 From 810619072a7760339379ca3802d956c976fc22dd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 28 Feb 2015 18:50:18 -0500 Subject: XEEN: gcc compilation fixes --- engines/xeen/character.cpp | 8 ++++---- engines/xeen/dialogs_items.cpp | 10 +++++----- engines/xeen/dialogs_spells.cpp | 8 ++++---- engines/xeen/module.mk | 6 +++--- engines/xeen/spells.cpp | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index ea0f9f532e..ca224ab4f1 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -300,7 +300,7 @@ Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) { Resources &res = *vm()->_resources; return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum, - !i._bonusFlags ? res._maeNames[i._material] : "", + !i._bonusFlags ? res._maeNames[i._material].c_str() : "", (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", WEAPON_NAMES[i._id], @@ -466,7 +466,7 @@ Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) { Resources &res = *vm()->_resources; return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, - !i._bonusFlags ? "" : res._maeNames[i._material], + !i._bonusFlags ? "" : res._maeNames[i._material].c_str(), (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", ARMOR_NAMES[i._id], @@ -589,7 +589,7 @@ Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum) Resources &res = *vm()->_resources; return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, - !i._bonusFlags ? "" : res._maeNames[i._material], + !i._bonusFlags ? "" : res._maeNames[i._material].c_str(), (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", ARMOR_NAMES[i._id], @@ -638,7 +638,7 @@ Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) { Resources &res = *vm()->_resources; return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, - !i._bonusFlags ? "" : res._maeNames[i._material], + !i._bonusFlags ? "" : res._maeNames[i._material].c_str(), (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", ARMOR_NAMES[i._id], diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index 21a8856e3c..bdcdffaa84 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -149,11 +149,11 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { || mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) { lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, arr[idx], idx + 1, - c->_items[category].getFullDescription(idx, arr[idx]))); + c->_items[category].getFullDescription(idx, arr[idx]).c_str())); } else { lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2, arr[idx], idx + 1, - c->_items[category].getFullDescription(idx, arr[idx]), + c->_items[category].getFullDescription(idx, arr[idx]).c_str(), calcItemCost(c, idx, mode, mode == ITEMMODE_TO_GOLD ? 1 : startingChar->_skills[MERCHANT], category) @@ -194,7 +194,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2, arr[idx], idx + 1, - c->_items[category].getFullDescription(idx, arr[idx]), + c->_items[category].getFullDescription(idx, arr[idx]).c_str(), calcItemCost(c, idx, tempMode, skill, category) )); } @@ -1002,7 +1002,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite int cost = calcItemCost(&c, itemIndex, mode, actionIndex, category); Common::String msg = Common::String::format(FIX_IDENTIFY_GOLD, FIX_IDENTIFY[0], - c._items[category].getFullDescription(itemIndex), + c._items[category].getFullDescription(itemIndex).c_str(), cost); if (Confirm::show(_vm, msg) && party.subtract(0, cost, 0)) { @@ -1015,7 +1015,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite int cost = calcItemCost(&c, itemIndex, mode, actionIndex, category); Common::String msg = Common::String::format(FIX_IDENTIFY_GOLD, FIX_IDENTIFY[1], - c._items[category].getFullDescription(itemIndex), + c._items[category].getFullDescription(itemIndex).c_str(), cost); if (Confirm::show(_vm, msg) && party.subtract(0, cost, 0)) { diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 08828a0c8d..70668e2ea5 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -67,7 +67,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int Common::String title = Common::String::format(BUY_SPELLS, c->_name.c_str()); Common::String msg = Common::String::format(GUILD_OPTIONS, - title.c_str(), XeenEngine::printMil(party._gold)); + title.c_str(), XeenEngine::printMil(party._gold).c_str()); screen._windows[10].writeString(msg); warning("TODO: Sprite draw using previously used button sprites"); @@ -353,7 +353,7 @@ const char *SpellsDialog::setSpellText(Character *c, int isCasting) { if (!c->_spells[idx] || (isCasting & 0x80)) { int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor); _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u", - spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), + spells._spellNames[SPELLS_ALLOWED[category][idx]].c_str(), cost), idx, spellId)); } } @@ -370,7 +370,7 @@ const char *SpellsDialog::setSpellText(Character *c, int isCasting) { if (!c->_spells[idx] || (isCasting & 0x80)) { int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor); _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u", - spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), + spells._spellNames[SPELLS_ALLOWED[category][idx]].c_str(), cost), idx, spellId)); } } @@ -385,7 +385,7 @@ const char *SpellsDialog::setSpellText(Character *c, int isCasting) { if (!c->_spells[idx] || (isCasting & 0x80)) { int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor); _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u", - spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), + spells._spellNames[SPELLS_ALLOWED[category][idx]].c_str(), cost), idx, spellId)); } } diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 1fe29c6a8e..4e64b8e815 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -1,9 +1,9 @@ MODULE := engines/xeen MODULE_OBJS := \ - clouds\clouds_game.o \ - darkside\darkside_game.o \ - worldofxeen\worldofxeen_game.o \ + clouds/clouds_game.o \ + darkside/darkside_game.o \ + worldofxeen/worldofxeen_game.o \ character.o \ combat.o \ debugger.o \ diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index d446b3ce6e..8166a1b029 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -151,7 +151,7 @@ int Spells::castSpell(Character *c, int spellId) { // Return the spell costs and flag that another spell can be selected addSpellCost(*c, spellId); ErrorDialog::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED, - _spellNames[spellId])); + _spellNames[spellId].c_str())); result = -1; } break; -- cgit v1.2.3 From b414ff26f2319e4d88c60f1b0fb58880926da5f0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 28 Feb 2015 19:22:42 -0500 Subject: XEEN: Implement some of the spells --- engines/xeen/spells.cpp | 147 ++++++++++++++++++++++++++++++++++++++++++++---- engines/xeen/spells.h | 2 +- 2 files changed, 137 insertions(+), 12 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 8166a1b029..1e883e7dda 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -75,7 +75,7 @@ void Spells::executeSpell(int spellId) { &Spells::curePoison, &Spells::acidSpray, &Spells::timeDistortion, &Spells::dragonSleep, - &Spells::cureDisease, &Spells::teleport, &Spells::fingerOfDeath, + &Spells::suppressPoison, &Spells::teleport, &Spells::fingerOfDeath, &Spells::cureParalysis, &Spells::golemStopper, &Spells::poisonVolley, &Spells::deadlySwarm, &Spells::superShelter, &Spells::dayOfProtection, &Spells::dayOfSorcery, @@ -264,18 +264,144 @@ void Spells::firstAid() { } } -void Spells::flyingFist() { error("TODO: spell"); } -void Spells::energyBlast() { error("TODO: spell"); } -void Spells::sleep() { error("TODO: spell"); } -void Spells::revitalize() { error("TODO: spell"); } -void Spells::cureWounds() { error("TODO: spell"); } -void Spells::sparks() { error("TODO: spell"); } +void Spells::flyingFist() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 6; + combat._damageType = DT_PHYSICAL; + combat._rangeType = RT_SINGLE; + sound.playFX(18); + combat.multiAttack(14); +} + +void Spells::energyBlast() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2; + combat._damageType = DT_ENERGY; + combat._rangeType = RT_SINGLE; + sound.playFX(16); + combat.multiAttack(13); +} + +void Spells::sleep() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 0; + combat._damageType = DT_SLEEP; + combat._rangeType = RT_GROUP; + sound.playFX(18); + combat.multiAttack(7); +} + +void Spells::revitalize() { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + int charIndex = SpellOnWho::show(_vm, MS_Revitalize); + if (charIndex == -1) + return; + + Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : + party._activeParty[charIndex]; + + sound.playFX(30); + c.addHitPoints(0); + c._conditions[WEAK] = 0; + intf.drawParty(true); +} + +void Spells::cureWounds() { + Combat &combat = *_vm->_combat; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + int charIndex = SpellOnWho::show(_vm, MS_Revitalize); + if (charIndex == -1) + return; + + Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : + party._activeParty[charIndex]; + + if (c.isDead()) { + spellFailed(); + } else { + sound.playFX(30); + c.addHitPoints(15); + } +} + +void Spells::sparks() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2; + combat._damageType = DT_ELECTRICAL; + combat._rangeType = RT_GROUP; + sound.playFX(14); + combat.multiAttack(5); +} void Spells::shrapMetal() { error("TODO: spell"); } void Spells::insectSpray() { error("TODO: spell"); } -void Spells::toxicCloud() { error("TODO: spell"); } -void Spells::protectionFromElements() { error("TODO: spell"); } -void Spells::pain() { error("TODO: spell"); } + +void Spells::toxicCloud() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 10; + combat._damageType = DT_POISON; + combat._rangeType = RT_GROUP; + sound.playFX(17); + combat.multiAttack(10); +} + +void Spells::suppressPoison() { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + int charIndex = SpellOnWho::show(_vm, MS_FirstAid); + if (charIndex == -1) + return; + + Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : + party._activeParty[charIndex]; + + if (c._conditions[POISONED]) { + if (c._conditions[POISONED] >= 4) { + c._conditions[POISONED] -= 2; + } else { + c._conditions[POISONED] = 1; + } + } + + sound.playFX(20); + c.addHitPoints(0); + intf.drawParty(1); +} + +void Spells::protectionFromElements() { + error("TODO: spell"); +} + +void Spells::pain() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 0; + combat._damageType = DT_PHYSICAL; + combat._rangeType = RT_GROUP; + sound.playFX(18); + combat.multiAttack(14); +} + void Spells::jump() { error("TODO: spell"); } // Not while engaged void Spells::beastMaster() { error("TODO: spell"); } void Spells::clairvoyance() { error("TODO: spell"); } @@ -304,7 +430,6 @@ void Spells::acidSpray() { error("TODO: spell"); } void Spells::timeDistortion() { error("TODO: spell"); } void Spells::dragonSleep() { error("TODO: spell"); } -void Spells::cureDisease() { error("TODO: spell"); } void Spells::teleport() { error("TODO: spell"); } // Not while engaged void Spells:: fingerOfDeath() { error("TODO: spell"); } void Spells::cureParalysis() { error("TODO: spell"); } diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h index 2f79670df0..f71f1fd458 100644 --- a/engines/xeen/spells.h +++ b/engines/xeen/spells.h @@ -116,7 +116,7 @@ private: void timeDistortion(); void dragonSleep(); - void cureDisease(); + void suppressPoison(); void teleport(); // Not while engaged void fingerOfDeath(); void cureParalysis(); -- cgit v1.2.3 From 9789962605a30e8a993370d3de3c1a30582f3964 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 28 Feb 2015 20:43:07 -0500 Subject: XEEN: Implemented protection from elements spell --- engines/xeen/dialogs_spells.cpp | 83 +++++++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_spells.h | 14 +++++++ engines/xeen/resources.cpp | 10 +++++ engines/xeen/resources.h | 3 ++ engines/xeen/spells.cpp | 30 ++++++++++++++- 5 files changed, 139 insertions(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 70668e2ea5..3aa0cfa4ad 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -644,4 +644,87 @@ int SpellOnWho::execute(int spellId) { return result; } +/*------------------------------------------------------------------------*/ + +int SelectElement::show(XeenEngine *vm, int spellId) { + SelectElement *dlg = new SelectElement(vm); + int result = dlg->execute(spellId); + delete dlg; + + return result; +} + +int SelectElement::execute(int spellId) { + Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + Spells &spells = *_vm->_spells; + Window &w = screen._windows[15]; + Mode oldMode = _vm->_mode; + _vm->_mode = MODE_3; + int result = 999; + + loadButtons(); + + w.open(); + w.writeString(WHICH_ELEMENT1); + drawButtons(&screen); + w.update(); + + while (result == 999) { + do { + events.updateGameCounter(); + intf.draw3d(true); + w.frame(); + w.writeString(WHICH_ELEMENT2); + drawButtons(&screen); + w.update(); + + do { + events.pollEventsAndWait(); + if (_vm->shouldQuit()) + return -1; + + checkEvents(_vm); + } while (!_buttonValue && events.timeElapsed() < 1); + } while (!_buttonValue); + + switch (_buttonValue) { + case Common::KEYCODE_ESCAPE: + result = -1; + spells.addSpellCost(*combat._oldCharacter, spellId); + break; + + case Common::KEYCODE_a: + result = DT_POISON; + break; + case Common::KEYCODE_c: + result = DT_COLD; + break; + case Common::KEYCODE_e: + result = DT_ELECTRICAL; + break; + case Common::KEYCODE_f: + result = DT_FIRE; + break; + default: + break; + } + } + + w.close(); + _vm->_mode = oldMode; + return result; +} + +void SelectElement::loadButtons() { + _iconSprites.load("element.icn"); + addButton(Common::Rect(60, 92, 84, 112), Common::KEYCODE_f, &_iconSprites); + addButton(Common::Rect(90, 92, 114, 112), Common::KEYCODE_e, &_iconSprites); + addButton(Common::Rect(120, 92, 144, 112), Common::KEYCODE_c, &_iconSprites); + addButton(Common::Rect(150, 92, 174, 112), Common::KEYCODE_a, &_iconSprites); +} + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h index 660f2ef1de..6bbdb3cddc 100644 --- a/engines/xeen/dialogs_spells.h +++ b/engines/xeen/dialogs_spells.h @@ -84,6 +84,20 @@ public: static int show(XeenEngine *vm, int spellId); }; +class SelectElement : public ButtonContainer { +private: + XeenEngine *_vm; + SpriteResource _iconSprites; + + SelectElement(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + int execute(int spellId); + + void loadButtons(); +public: + static int show(XeenEngine *vm, int spellId); +}; + } // End of namespace Xeen #endif /* XEEN_DIALOGS_SPELLS_H */ diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 5893403ebd..3a751b7ad9 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1530,4 +1530,14 @@ const char *const X_FOUND_Y = "\v060\t000\x03c%s found: %s"; const char *const ON_WHO = "\x3""c\v009On Who?"; +const char *const WHICH_ELEMENT = ""; + +const char *const WHICH_ELEMENT1 = + "\r\x3""c\x1Which Element?\x2\v034\t014\f15F\fdire\t044" + "\f15E\fdlec\t074\f15C\fdold\t104\f15A\fdcid\x1"; + +const char *const WHICH_ELEMENT2 = + "\r\x3""cWhich Element?', 2, 0Bh, '034\t014\f15F\fdire\t044" + "\f15E\fdlec\t074\f15C\fdold\t104\f15A\fdcid\x1"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index b908d91cf9..fed249108d 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -541,6 +541,9 @@ extern const char *const X_FOUND_Y; extern const char *const ON_WHO; +extern const char *const WHICH_ELEMENT1; +extern const char *const WHICH_ELEMENT2; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 1e883e7dda..b2b477e54d 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -388,7 +388,35 @@ void Spells::suppressPoison() { } void Spells::protectionFromElements() { - error("TODO: spell"); + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + Character &c = *combat._oldCharacter; + int resist = MIN(c.getCurrentLevel() * 2 + 5, (uint)200); + + int elementType = SelectElement::show(_vm, MS_ProtFromElements); + if (elementType != -1) { + switch (elementType) { + case DT_FIRE: + party._fireResistence = resist; + break; + case DT_ELECTRICAL: + party._fireResistence = resist; + break; + case DT_COLD: + party._coldResistence = resist; + break; + case DT_POISON: + party._poisonResistence = resist; + break; + default: + break; + } + + sound.playFX(20); + intf.drawParty(true); + } } void Spells::pain() { -- cgit v1.2.3 From 07f504fe160d051c458e1f0035d4784ac74e2530 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 28 Feb 2015 22:53:17 -0500 Subject: XEEN: Fix ordering of spell list and methods --- engines/xeen/combat.cpp | 6 +- engines/xeen/dialogs_spells.cpp | 31 ++- engines/xeen/dialogs_spells.h | 12 + engines/xeen/interface.cpp | 4 +- engines/xeen/resources.cpp | 6 +- engines/xeen/resources.h | 2 + engines/xeen/spells.cpp | 556 ++++++++++++++++++++++++++-------------- engines/xeen/spells.h | 140 +++++----- 8 files changed, 481 insertions(+), 276 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 7cc2ab6b22..1d03a5128d 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -64,10 +64,6 @@ static const int MONSTER_GRID_BITINDEX2[48] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static const int MONSTER_GRID_BITMASK[12] = { - 0xC, 8, 4, 0, 0xF, 0xF000, 0xF00, 0xF0, 0xF00, 0xF0, 0x0F, 0xF000 -}; - static const int ATTACK_TYPE_FX[23] = { 49, 18, 13, 14, 15, 17, 16, 0, 6, 1, 2, 3, 4, 5, 4, 9, 27, 29, 44, 51, 53, 61, 71 @@ -1598,7 +1594,7 @@ void Combat::quickFight() { break; case QUICK_SPELL: if (c->_currentSpell != -1) { - spells.castSpell(c, SPELLS_ALLOWED[c->getClassCategory()][c->_currentSpell]); + spells.castSpell(c, (MagicSpell)SPELLS_ALLOWED[c->getClassCategory()][c->_currentSpell]); } break; case QUICK_BLOCK: diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 3aa0cfa4ad..dfc72aa4b1 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -658,7 +658,6 @@ int SelectElement::execute(int spellId) { Combat &combat = *_vm->_combat; EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; - Party &party = *_vm->_party; Screen &screen = *_vm->_screen; Spells &spells = *_vm->_spells; Window &w = screen._windows[15]; @@ -727,4 +726,34 @@ void SelectElement::loadButtons() { addButton(Common::Rect(150, 92, 174, 112), Common::KEYCODE_a, &_iconSprites); } +/*------------------------------------------------------------------------*/ + +void NotWhileEngaged::show(XeenEngine *vm, int spellId) { + NotWhileEngaged *dlg = new NotWhileEngaged(vm); + dlg->execute(spellId); + delete dlg; +} + +void NotWhileEngaged::execute(int spellId) { + EventsManager &events = *_vm->_events; + Screen &screen = *_vm->_screen; + Spells &spells = *_vm->_spells; + Window &w = screen._windows[6]; + Mode oldMode = _vm->_mode; + _vm->_mode = MODE_3; + + w.open(); + w.writeString(Common::String::format(CANT_CAST_WHILE_ENGAGED, + spells._spellNames[spellId].c_str())); + w.update(); + + while (!_vm->shouldQuit() && !events.isKeyMousePressed()) + events.pollEventsAndWait(); + events.clearEvents(); + + w.close(); + _vm->_mode = oldMode; +} + + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h index 6bbdb3cddc..b23f62b22f 100644 --- a/engines/xeen/dialogs_spells.h +++ b/engines/xeen/dialogs_spells.h @@ -98,6 +98,18 @@ public: static int show(XeenEngine *vm, int spellId); }; +class NotWhileEngaged : public ButtonContainer { +private: + XeenEngine *_vm; + + NotWhileEngaged(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + void execute(int spellId); +public: + static void show(XeenEngine *vm, int spellId); +}; + + } // End of namespace Xeen #endif /* XEEN_DIALOGS_SPELLS_H */ diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 923eaeac0b..d1a1478d95 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -541,7 +541,7 @@ void Interface::perform() { if (spellId == -1 || c == nullptr) break; - result = spells.castSpell(c, spellId); + result = spells.castSpell(c, (MagicSpell)spellId); } while (result != -1); if (result == 1) { @@ -2008,7 +2008,7 @@ void Interface::doCombat() { int spellId = CastSpell::show(_vm); if (spellId != -1) { Character *c = combat._combatParty[combat._whosTurn]; - spells.castSpell(c, spellId); + spells.castSpell(c, (MagicSpell)spellId); nextChar(); } else { highlightChar(combat._combatParty[combat._whosTurn]->_rosterId); diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 3a751b7ad9..228c5f6449 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -438,6 +438,10 @@ const int8 SCREEN_POSITIONING_Y[4][48] = { } }; +const int MONSTER_GRID_BITMASK[12] = { + 0xC, 8, 4, 0, 0xF, 0xF000, 0xF00, 0xF0, 0xF00, 0xF0, 0x0F, 0xF000 +}; + const int INDOOR_OBJECT_X[2][12] = { { 5, -7, -112, 98, -8, -65, 49, -9, -34, 16, -58, 40 }, { -35, -35, -142, 68, -35, -95, 19, -35, -62, -14, -98, 16 } @@ -827,7 +831,7 @@ const int MISC_SPELL_INDEX[74] = { MS_Levitate, MS_WizardEye, MS_Bless, MS_IdentifyMonster, MS_LightningBolt, MS_HolyBonus, MS_PowerCure, MS_NaturesCure, MS_LloydsBeacon, MS_PowerShield, MS_Heroism, MS_Hynotize, - MS_WalkOnWater, MS_FrostBite, MS_DetectMonster, MS_FireBall, + MS_WalkOnWater, MS_FrostBite, MS_DetectMonster, MS_Fireball, MS_ColdRay, MS_CurePoison, MS_AcidSpray, MS_TimeDistortion, MS_DragonSleep, MS_CureDisease, MS_Teleport, MS_FingerOfDeath, MS_CureParalysis, MS_GolemStopper, MS_PoisonVolley, MS_DeadlySwarm, diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index fed249108d..84a4648e84 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -127,6 +127,8 @@ extern const int8 SCREEN_POSITIONING_X[4][48]; extern const int8 SCREEN_POSITIONING_Y[4][48]; +extern const int MONSTER_GRID_BITMASK[12]; + extern const int INDOOR_OBJECT_X[2][12]; extern const int MAP_OBJECT_Y[2][12]; diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index b2b477e54d..f5f6428b9f 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -54,43 +54,34 @@ int Spells::calcSpellPoints(int spellId, int expenseFactor) const { typedef void(Spells::*SpellMethodPtr)(); -void Spells::executeSpell(int spellId) { - static const SpellMethodPtr SPELL_LIST[73] = { - &Spells::light, &Spells::awaken, &Spells::magicArrow, &Spells::firstAid, - &Spells::flyingFist, &Spells::energyBlast, &Spells::sleep, - &Spells::revitalize, &Spells::cureWounds, &Spells::sparks, - - &Spells::shrapMetal, &Spells::insectSpray, &Spells::toxicCloud, - &Spells::protectionFromElements, &Spells::pain, &Spells::jump, - &Spells::beastMaster, &Spells::clairvoyance, &Spells::turnUndead, - &Spells::levitate, - - &Spells::wizardEye, &Spells::bless, &Spells::identifyMonster, - &Spells::lightningBolt, &Spells::holyBonus, &Spells::powerCure, - &Spells::naturesCure, &Spells::lloydsBeacon, &Spells::powerShield, - &Spells::heroism, - - &Spells::hypnotize, &Spells::walkOnWater, &Spells::frostByte, - &Spells::detectMonster, &Spells::fireball, &Spells::coldRay, - &Spells::curePoison, &Spells::acidSpray, &Spells::timeDistortion, - &Spells::dragonSleep, - - &Spells::suppressPoison, &Spells::teleport, &Spells::fingerOfDeath, - &Spells::cureParalysis, &Spells::golemStopper, &Spells::poisonVolley, - &Spells::deadlySwarm, &Spells::superShelter, &Spells::dayOfProtection, - &Spells::dayOfSorcery, - - &Spells::createFood, &Spells::fieryFlail, &Spells::rechargeItem, - &Spells::fantasticFreeze, &Spells::townPortal, &Spells::stoneToFlesh, - &Spells::raiseDead, &Spells::etherialize, &Spells::dancingSword, - &Spells::moonRay, - - &Spells::massDistortion, &Spells::prismaticLight, &Spells::enchantItem, - &Spells::incinerate, &Spells::holyWord, &Spells::resurrection, - &Spells::elementalStorm, &Spells::megaVolts, &Spells::inferno, - &Spells::sunRay, - - &Spells::implosion, &Spells::starBurst, &Spells::divineIntervention +void Spells::executeSpell(MagicSpell spellId) { + static const SpellMethodPtr SPELL_LIST[76] = { + &Spells::acidSpray, &Spells::awaken, &Spells::beastMaster, + &Spells::bless, &Spells::clairvoyance, &Spells::coldRay, + &Spells::createFood, &Spells::cureDisease, &Spells::cureParalysis, + &Spells::curePoison, &Spells::cureWounds, &Spells::dancingSword, + &Spells::dayOfProtection, &Spells::dayOfSorcery, &Spells::deadlySwarm, + &Spells::detectMonster, &Spells::divineIntervention, &Spells::dragonSleep, + &Spells::elementalStorm, &Spells::enchantItem, &Spells::energyBlast, + &Spells::etherialize, &Spells::fantasticFreeze, &Spells::fieryFlail, + &Spells::fingerOfDeath, &Spells::fireball, &Spells::firstAid, + &Spells::flyingFist, &Spells::frostbite, &Spells::golemStopper, + &Spells::heroism, &Spells::holyBonus, &Spells::holyWord, + &Spells::hypnotize, &Spells::identifyMonster, &Spells::implosion, + &Spells::incinerate, &Spells::inferno, &Spells::insectSpray, + &Spells::itemToGold, &Spells::jump, &Spells::levitate, + &Spells::light, &Spells::lightningBolt, &Spells::lloydsBeacon, + &Spells::magicArrow, &Spells::massDistortion, &Spells::megaVolts, + &Spells::moonRay, &Spells::naturesCure, &Spells::pain, + &Spells::poisonVolley, &Spells::powerCure, &Spells::powerShield, + &Spells::prismaticLight, &Spells::protectionFromElements, &Spells::raiseDead, + &Spells::rechargeItem, &Spells::resurrection, &Spells::revitalize, + &Spells::shrapMetal, &Spells::sleep, &Spells::sparks, + &Spells::starBurst, &Spells::stoneToFlesh, &Spells::sunRay, + &Spells::superShelter, &Spells::suppressDisease, &Spells::suppressPoison, + &Spells::teleport, &Spells::timeDistortion, &Spells::townPortal, + &Spells::toxicCloud, &Spells::turnUndead, &Spells::walkOnWater, + &Spells::wizardEye }; (this->*SPELL_LIST[spellId])(); @@ -106,23 +97,82 @@ void Spells::spellFailed() { /** * Cast a spell associated with an item */ -void Spells::castItemSpell(int spellId) { - if (_vm->_mode == MODE_COMBAT) { - if (spellId == 15 || spellId == 20 || spellId == 27 || spellId == 41 - || spellId == 47 || spellId == 54 || spellId == 57) { - ErrorDialog::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED, - _spellNames[spellId].c_str())); +void Spells::castItemSpell(int itemSpellId) { + switch (itemSpellId) { + case 15: + if (_vm->_mode == MODE_COMBAT) { + NotWhileEngaged::show(_vm, MS_Jump); return; } + break; + case 20: + if (_vm->_mode == MODE_COMBAT) { + NotWhileEngaged::show(_vm, MS_WizardEye); + return; + } + break; + case 27: + if (_vm->_mode == MODE_COMBAT) { + NotWhileEngaged::show(_vm, MS_LloydsBeacon); + return; + } + break; + case 32: + frostbite2(); + break; + case 41: + if (_vm->_mode == MODE_COMBAT) { + NotWhileEngaged::show(_vm, MS_Teleport); + return; + } + break; + case 47: + if (_vm->_mode == MODE_COMBAT) { + NotWhileEngaged::show(_vm, MS_SuperShelter); + return; + } + break; + case 54: + if (_vm->_mode == MODE_COMBAT) { + NotWhileEngaged::show(_vm, MS_TownPortal); + return; + } + break; + case 57: + if (_vm->_mode == MODE_COMBAT) { + NotWhileEngaged::show(_vm, MS_Etheralize); + return; + } + break; + default: + break; } - executeSpell(spellId); + static const MagicSpell spells[73] = { + MS_Light, MS_Awaken, MS_MagicArrow, MS_FirstAid, MS_FlyingFist, + MS_EnergyBlast, MS_Sleep, MS_Revitalize, MS_CureWounds, MS_Sparks, + MS_Shrapmetal, MS_InsectSpray, MS_ToxicCloud, MS_ProtFromElements, MS_Pain, + MS_Jump, MS_BeastMaster, MS_Clairvoyance, MS_TurnUndead, MS_Levitate, + MS_WizardEye, MS_Bless, MS_IdentifyMonster, MS_LightningBolt, MS_HolyBonus, + MS_PowerCure, MS_NaturesCure, MS_LloydsBeacon, MS_PowerShield, MS_Heroism, + MS_Hynotize, MS_WalkOnWater, NO_SPELL, MS_DetectMonster, MS_Fireball, + MS_ColdRay, MS_CurePoison, MS_AcidSpray, MS_TimeDistortion, MS_DragonSleep, + MS_CureDisease, MS_Teleport, MS_FingerOfDeath, MS_CureParalysis, MS_GolemStopper, + MS_PoisonVolley, MS_DeadlySwarm, MS_SuperShelter, MS_DayOfProtection, MS_DayOfProtection, + MS_CreateFood, MS_FieryFlail, MS_RechargeItem, MS_FantasticFreeze, MS_TownPortal, + MS_StoneToFlesh, MS_RaiseDead, MS_Etheralize, MS_DancingSword, MS_MoonRay, + MS_MassDistortion, MS_PrismaticLight, MS_EnchantItem, MS_Incinerate, MS_HolyWord, + MS_Resurrection, MS_ElementalStorm, MS_MegaVolts, MS_Inferno, MS_SunRay, + MS_Implosion, MS_StarBurst, MS_DivineIntervention + }; + + executeSpell(spells[itemSpellId]); } /** * Cast a given spell */ -int Spells::castSpell(Character *c, int spellId) { +int Spells::castSpell(Character *c, MagicSpell spellId) { Combat &combat = *_vm->_combat; Interface &intf = *_vm->_interface; int oldTillMove = intf._tillMove; @@ -137,21 +187,20 @@ int Spells::castSpell(Character *c, int spellId) { } else { // Some spells have special handling switch (spellId) { - case 19: // Enchant item - case 21: // Etherialize - case 40: // Jump - case 44: // Lloyd's Beacon - case 66: // Super Shelter - case 69: // Teleport - case 71: // Town Portal - case 75: // Wizard Eye + case MS_EnchantItem: + case MS_Etheralize: + case MS_Jump: + case MS_LloydsBeacon: + case MS_SuperShelter: + case MS_Teleport: + case MS_TownPortal: + case MS_WizardEye: if (_vm->_mode != MODE_COMBAT) { executeSpell(spellId); } else { // Return the spell costs and flag that another spell can be selected addSpellCost(*c, spellId); - ErrorDialog::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED, - _spellNames[spellId].c_str())); + NotWhileEngaged::show(_vm, spellId); result = -1; } break; @@ -209,18 +258,9 @@ void Spells::addSpellCost(Character &c, int spellId) { party._gems += gemCost; } -void Spells::light() { - Interface &intf = *_vm->_interface; - Party &party = *_vm->_party; - SoundManager &sound = *_vm->_sound; - - ++party._lightCount; - if (intf._intrIndex1) - party._stepped = true; - sound.playFX(39); -} +void Spells::acidSpray() { error("TODO: spell"); } -void Spells::awaken() { +void Spells::awaken() { Interface &intf = *_vm->_interface; Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; @@ -236,14 +276,82 @@ void Spells::awaken() { sound.playFX(30); } -void Spells::magicArrow() { +void Spells::beastMaster() { error("TODO: spell"); } + +void Spells::bless() { error("TODO: spell"); } + +void Spells::clairvoyance() { error("TODO: spell"); } + +void Spells::coldRay() { error("TODO: spell"); } + +void Spells::createFood() { error("TODO: spell"); } + +void Spells::cureDisease() { error("TODO: spell"); } + +void Spells::cureParalysis() { error("TODO: spell"); } + +void Spells::curePoison() { error("TODO: spell"); } + +void Spells::cureWounds() { Combat &combat = *_vm->_combat; - combat._monsterDamage = 0; - combat._damageType = DT_MAGIC_ARROW; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + int charIndex = SpellOnWho::show(_vm, MS_Revitalize); + if (charIndex == -1) + return; + + Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : + party._activeParty[charIndex]; + + if (c.isDead()) { + spellFailed(); + } + else { + sound.playFX(30); + c.addHitPoints(15); + } +} + +void Spells::dancingSword() { error("TODO: spell"); } + +void Spells::dayOfProtection() { error("TODO: spell"); } + +void Spells::dayOfSorcery() { error("TODO: spell"); } + +void Spells::deadlySwarm() { error("TODO: spell"); } + +void Spells::detectMonster() { error("TODO: spell"); } + +void Spells::divineIntervention() { error("TODO: spell"); } + +void Spells::dragonSleep() { error("TODO: spell"); } + +void Spells::elementalStorm() { error("TODO: spell"); } + +void Spells::enchantItem() { error("TODO: spell"); } + +void Spells::energyBlast() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2; + combat._damageType = DT_ENERGY; combat._rangeType = RT_SINGLE; - combat.multiAttack(11); + sound.playFX(16); + combat.multiAttack(13); } +void Spells::etherialize() { error("TODO: spell"); } // Not while engaged + +void Spells::fantasticFreeze() { error("TODO: spell"); } + +void Spells::fieryFlail() { error("TODO: spell"); } + +void Spells::fingerOfDeath() { error("TODO: spell"); } + +void Spells::fireball() { error("TODO: spell"); } + void Spells::firstAid() { Combat &combat = *_vm->_combat; Party &party = *_vm->_party; @@ -258,7 +366,8 @@ void Spells::firstAid() { if (c.isDead()) { spellFailed(); - } else { + } + else { sound.playFX(30); c.addHitPoints(6); } @@ -275,28 +384,158 @@ void Spells::flyingFist() { combat.multiAttack(14); } -void Spells::energyBlast() { - Combat &combat = *_vm->_combat; +void Spells::frostbite() { error("TODO: spell"); } + +void Spells::golemStopper() { error("TODO: spell"); } + +void Spells::heroism() { error("TODO: spell"); } + +void Spells::holyBonus() { error("TODO: spell"); } + +void Spells::holyWord() { error("TODO: spell"); } + +void Spells::hypnotize() { error("TODO: spell"); } + +void Spells::identifyMonster() { error("TODO: spell"); } + +void Spells::implosion() { error("TODO: spell"); } + +void Spells::incinerate() { error("TODO: spell"); } + +void Spells::inferno() { error("TODO: spell"); } + +void Spells::insectSpray() { error("TODO: spell"); } + +void Spells::itemToGold() { error("TODO: spell"); } + +void Spells::jump() { + Map &map = *_vm->_map; + Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; - combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2; - combat._damageType = DT_ENERGY; + if (map._isOutdoors) { + map.getCell(7); + if (map._currentWall != 1) { + map.getCell(14); + if (map._currentSurfaceId != 0 && map._currentWall != 1) { + party._mazePosition += Common::Point( + SCREEN_POSITIONING_X[party._mazeDirection][14], + SCREEN_POSITIONING_Y[party._mazeDirection][14] + ); + sound.playFX(51); + party._stepped = true; + return; + } + } + } else { + Common::Point pt = party._mazePosition + Common::Point( + SCREEN_POSITIONING_X[party._mazeDirection][7], + SCREEN_POSITIONING_Y[party._mazeDirection][7]); + if (!map.mazeLookup(party._mazePosition, MONSTER_GRID_BITMASK[party._mazeDirection]) && + !map.mazeLookup(pt, MONSTER_GRID_BITMASK[party._mazeDirection])) { + party._mazePosition += Common::Point( + SCREEN_POSITIONING_X[party._mazeDirection][14], + SCREEN_POSITIONING_Y[party._mazeDirection][14] + ); + sound.playFX(51); + party._stepped = true; + return; + } + } + + spellFailed(); +} + +void Spells::levitate() { error("TODO: spell"); } + +void Spells::light() { + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + ++party._lightCount; + if (intf._intrIndex1) + party._stepped = true; + sound.playFX(39); +} + +void Spells::lightningBolt() { error("TODO: spell"); } + +void Spells::lloydsBeacon() { error("TODO: spell"); } // Not while engaged + +void Spells::magicArrow() { + Combat &combat = *_vm->_combat; + combat._monsterDamage = 0; + combat._damageType = DT_MAGIC_ARROW; combat._rangeType = RT_SINGLE; - sound.playFX(16); - combat.multiAttack(13); + combat.multiAttack(11); } -void Spells::sleep() { +void Spells::massDistortion() { error("TODO: spell"); } + +void Spells::megaVolts() { error("TODO: spell"); } + +void Spells::moonRay() { error("TODO: spell"); } + +void Spells::naturesCure() { error("TODO: spell"); } + +void Spells::pain() { Combat &combat = *_vm->_combat; SoundManager &sound = *_vm->_sound; combat._monsterDamage = 0; - combat._damageType = DT_SLEEP; + combat._damageType = DT_PHYSICAL; combat._rangeType = RT_GROUP; sound.playFX(18); - combat.multiAttack(7); + combat.multiAttack(14); } +void Spells::poisonVolley() { error("TODO: spell"); } + +void Spells::powerCure() { error("TODO: spell"); } + +void Spells::powerShield() { error("TODO: spell"); } + +void Spells::prismaticLight() { error("TODO: spell"); } + +void Spells::protectionFromElements() { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + Character &c = *combat._oldCharacter; + int resist = MIN(c.getCurrentLevel() * 2 + 5, (uint)200); + + int elementType = SelectElement::show(_vm, MS_ProtFromElements); + if (elementType != -1) { + switch (elementType) { + case DT_FIRE: + party._fireResistence = resist; + break; + case DT_ELECTRICAL: + party._fireResistence = resist; + break; + case DT_COLD: + party._coldResistence = resist; + break; + case DT_POISON: + party._poisonResistence = resist; + break; + default: + break; + } + + sound.playFX(20); + intf.drawParty(true); + } +} + +void Spells::raiseDead() { error("TODO: spell"); } + +void Spells::rechargeItem() { error("TODO: spell"); } + +void Spells::resurrection() { error("TODO: spell"); } + void Spells::revitalize() { Combat &combat = *_vm->_combat; Interface &intf = *_vm->_interface; @@ -316,24 +555,17 @@ void Spells::revitalize() { intf.drawParty(true); } -void Spells::cureWounds() { +void Spells::shrapMetal() { error("TODO: spell"); } + +void Spells::sleep() { Combat &combat = *_vm->_combat; - Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; - int charIndex = SpellOnWho::show(_vm, MS_Revitalize); - if (charIndex == -1) - return; - - Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : - party._activeParty[charIndex]; - - if (c.isDead()) { - spellFailed(); - } else { - sound.playFX(30); - c.addHitPoints(15); - } + combat._monsterDamage = 0; + combat._damageType = DT_SLEEP; + combat._rangeType = RT_GROUP; + sound.playFX(18); + combat.multiAttack(7); } void Spells::sparks() { @@ -347,19 +579,15 @@ void Spells::sparks() { combat.multiAttack(5); } -void Spells::shrapMetal() { error("TODO: spell"); } -void Spells::insectSpray() { error("TODO: spell"); } +void Spells::starBurst() { error("TODO: spell"); } -void Spells::toxicCloud() { - Combat &combat = *_vm->_combat; - SoundManager &sound = *_vm->_sound; +void Spells::stoneToFlesh() { error("TODO: spell"); } - combat._monsterDamage = 10; - combat._damageType = DT_POISON; - combat._rangeType = RT_GROUP; - sound.playFX(17); - combat.multiAttack(10); -} +void Spells::sunRay() { error("TODO: spell"); } + +void Spells::superShelter() { error("TODO: spell"); } + +void Spells::suppressDisease() { error("TODO: spell"); } void Spells::suppressPoison() { Combat &combat = *_vm->_combat; @@ -387,111 +615,47 @@ void Spells::suppressPoison() { intf.drawParty(1); } -void Spells::protectionFromElements() { +void Spells::teleport() { error("TODO: spell"); } // Not while engaged + +void Spells::timeDistortion() { error("TODO: spell"); } + +void Spells::townPortal() { error("TODO: spell"); } // Not while engaged + +void Spells::toxicCloud() { Combat &combat = *_vm->_combat; - Interface &intf = *_vm->_interface; - Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; - Character &c = *combat._oldCharacter; - int resist = MIN(c.getCurrentLevel() * 2 + 5, (uint)200); - - int elementType = SelectElement::show(_vm, MS_ProtFromElements); - if (elementType != -1) { - switch (elementType) { - case DT_FIRE: - party._fireResistence = resist; - break; - case DT_ELECTRICAL: - party._fireResistence = resist; - break; - case DT_COLD: - party._coldResistence = resist; - break; - case DT_POISON: - party._poisonResistence = resist; - break; - default: - break; - } - sound.playFX(20); - intf.drawParty(true); - } + combat._monsterDamage = 10; + combat._damageType = DT_POISON; + combat._rangeType = RT_GROUP; + sound.playFX(17); + combat.multiAttack(10); } -void Spells::pain() { +void Spells::turnUndead() { Combat &combat = *_vm->_combat; SoundManager &sound = *_vm->_sound; combat._monsterDamage = 0; - combat._damageType = DT_PHYSICAL; + combat._damageType = DT_UNDEAD; combat._rangeType = RT_GROUP; sound.playFX(18); - combat.multiAttack(14); + combat.multiAttack(13); } -void Spells::jump() { error("TODO: spell"); } // Not while engaged -void Spells::beastMaster() { error("TODO: spell"); } -void Spells::clairvoyance() { error("TODO: spell"); } -void Spells::turnUndead() { error("TODO: spell"); } -void Spells::levitate() { error("TODO: spell"); } - -void Spells::wizardEye() { error("TODO: spell"); } // Not while engaged -void Spells::bless() { error("TODO: spell"); } -void Spells::identifyMonster() { error("TODO: spell"); } -void Spells::lightningBolt() { error("TODO: spell"); } -void Spells::holyBonus() { error("TODO: spell"); } -void Spells::powerCure() { error("TODO: spell"); } -void Spells::naturesCure() { error("TODO: spell"); } -void Spells::lloydsBeacon() { error("TODO: spell"); } // Not while engaged -void Spells::powerShield() { error("TODO: spell"); } -void Spells::heroism() { error("TODO: spell"); } - -void Spells::hypnotize() { error("TODO: spell"); } void Spells::walkOnWater() { error("TODO: spell"); } -void Spells::frostByte() { error("TODO: spell"); } -void Spells::detectMonster() { error("TODO: spell"); } -void Spells::fireball() { error("TODO: spell"); } -void Spells::coldRay() { error("TODO: spell"); } -void Spells::curePoison() { error("TODO: spell"); } -void Spells::acidSpray() { error("TODO: spell"); } -void Spells::timeDistortion() { error("TODO: spell"); } -void Spells::dragonSleep() { error("TODO: spell"); } -void Spells::teleport() { error("TODO: spell"); } // Not while engaged -void Spells:: fingerOfDeath() { error("TODO: spell"); } -void Spells::cureParalysis() { error("TODO: spell"); } -void Spells::golemStopper() { error("TODO: spell"); } -void Spells::poisonVolley() { error("TODO: spell"); } -void Spells::deadlySwarm() { error("TODO: spell"); } -void Spells::superShelter() { error("TODO: spell"); } // Not while engaged -void Spells::dayOfProtection() { error("TODO: spell"); } -void Spells::dayOfSorcery() { error("TODO: spell"); } - -void Spells::createFood() { error("TODO: spell"); } -void Spells::fieryFlail() { error("TODO: spell"); } -void Spells::rechargeItem() { error("TODO: spell"); } -void Spells::fantasticFreeze() { error("TODO: spell"); } -void Spells::townPortal() { error("TODO: spell"); } // Not while engaged -void Spells::stoneToFlesh() { error("TODO: spell"); } -void Spells::raiseDead() { error("TODO: spell"); } -void Spells::etherialize() { error("TODO: spell"); } // Not while engaged -void Spells::dancingSword() { error("TODO: spell"); } -void Spells::moonRay() { error("TODO: spell"); } - -void Spells::massDistortion() { error("TODO: spell"); } -void Spells::prismaticLight() { error("TODO: spell"); } -void Spells::enchantItem() { error("TODO: spell"); } -void Spells::incinerate() { error("TODO: spell"); } -void Spells::holyWord() { error("TODO: spell"); } -void Spells::resurrection() { error("TODO: spell"); } -void Spells::elementalStorm() { error("TODO: spell"); } -void Spells::megaVolts() { error("TODO: spell"); } -void Spells::inferno() { error("TODO: spell"); } -void Spells::sunRay() { error("TODO: spell"); } +void Spells::wizardEye() { error("TODO: spell"); } // Not while engaged -void Spells::implosion() { error("TODO: spell"); } -void Spells::starBurst() { error("TODO: spell"); } -void Spells::divineIntervention() { error("TODO: spell"); } +void Spells::frostbite2() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 35; + combat._damageType = DT_COLD; + combat._rangeType = RT_SINGLE; + sound.playFX(15); + combat.multiAttack(9); +} } // End of namespace Xeen diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h index f71f1fd458..1af4fb222f 100644 --- a/engines/xeen/spells.h +++ b/engines/xeen/spells.h @@ -42,7 +42,7 @@ enum MagicSpell { MS_DivineIntervention = 16, MS_DragonSleep = 17, MS_ElementalStorm = 18, MS_EnchantItem = 19, MS_EnergyBlast = 20, MS_Etheralize = 21, MS_FantasticFreeze = 22, MS_FieryFlail = 23, MS_FingerOfDeath = 24, - MS_FireBall = 25, MS_FirstAid = 26, MS_FlyingFist = 27, + MS_Fireball = 25, MS_FirstAid = 26, MS_FlyingFist = 27, MS_FrostBite = 28, MS_GolemStopper = 29, MS_Heroism = 30, MS_HolyBonus = 31, MS_HolyWord = 32, MS_Hynotize = 33, MS_IdentifyMonster = 34, MS_Implosion = 35, MS_Incinerate = 36, @@ -67,91 +67,89 @@ private: void load(); - void executeSpell(int spellId); + void executeSpell(MagicSpell spellId); void spellFailed(); // Spell list - void light(); + void acidSpray(); void awaken(); - void magicArrow(); - void firstAid(); - void flyingFist(); - void energyBlast(); - void sleep(); - void revitalize(); - void cureWounds(); - void sparks(); - - void shrapMetal(); - void insectSpray(); - void toxicCloud(); - void protectionFromElements(); - void pain(); - void jump(); // Not while engaged void beastMaster(); - void clairvoyance(); - void turnUndead(); - void levitate(); - - void wizardEye(); // Not while engaged void bless(); - void identifyMonster(); - void lightningBolt(); - void holyBonus(); - void powerCure(); - void naturesCure(); - void lloydsBeacon(); // Not while engaged - void powerShield(); - void heroism(); - - void hypnotize(); - void walkOnWater(); - void frostByte(); - void detectMonster(); - void fireball(); + void clairvoyance(); void coldRay(); - void curePoison(); - void acidSpray(); - void timeDistortion(); - void dragonSleep(); - - void suppressPoison(); - void teleport(); // Not while engaged - void fingerOfDeath(); + void createFood(); + void cureDisease(); void cureParalysis(); - void golemStopper(); - void poisonVolley(); - void deadlySwarm(); - void superShelter(); // Not while engaged + void curePoison(); + void cureWounds(); + void dancingSword(); void dayOfProtection(); void dayOfSorcery(); - - void createFood(); - void fieryFlail(); - void rechargeItem(); + void deadlySwarm(); + void detectMonster(); + void divineIntervention(); + void dragonSleep(); + void elementalStorm(); + void enchantItem(); + void energyBlast(); + void etherialize(); void fantasticFreeze(); - void townPortal(); // Not while engaged - void stoneToFlesh(); - void raiseDead(); - void etherialize(); // Not while engaged - void dancingSword(); - void moonRay(); - + void fieryFlail(); + void fingerOfDeath(); + void fireball(); + void firstAid(); + void flyingFist(); + void frostbite(); + void golemStopper(); + void heroism(); + void holyBonus(); + void holyWord(); + void hypnotize(); + void identifyMonster(); + void implosion(); + void incinerate(); + void inferno(); + void insectSpray(); + void itemToGold(); + void jump(); + void levitate(); + void light(); + void lightningBolt(); + void lloydsBeacon(); + void magicArrow(); void massDistortion(); + void megaVolts(); + void moonRay(); + void naturesCure(); + void pain(); + void poisonVolley(); + void powerCure(); + void powerShield(); void prismaticLight(); - void enchantItem(); - void incinerate(); - void holyWord(); + void protectionFromElements(); + void raiseDead(); + void rechargeItem(); void resurrection(); - void elementalStorm(); - void megaVolts(); - void inferno(); + void revitalize(); + void shrapMetal(); + void sleep(); + void sparks(); + void starBurst(); + void stoneToFlesh(); void sunRay(); + void superShelter(); + void suppressDisease(); + void suppressPoison(); + void teleport(); + void timeDistortion(); + void townPortal(); + void toxicCloud(); + void turnUndead(); + void walkOnWater(); + void wizardEye(); - void implosion(); - void starBurst(); - void divineIntervention(); + void frostbite2(); public: Common::StringArray _spellNames; int _lastCaster; @@ -162,9 +160,9 @@ public: int calcSpellPoints(int spellId, int expenseFactor) const; - void castItemSpell(int spellId); + void castItemSpell(int itemSpellId); - int castSpell(Character *c, int spellId); + int castSpell(Character *c, MagicSpell spellId); int subSpellCost(Character &c, int spellId); -- cgit v1.2.3 From b243768887c3aabbc6fe57e83971562bf2eba0f5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 1 Mar 2015 08:31:03 -0500 Subject: XEEN: Implementing spells --- engines/xeen/dialogs_spells.cpp | 107 ++++++++ engines/xeen/dialogs_spells.h | 13 + engines/xeen/resources.cpp | 10 + engines/xeen/resources.h | 4 + engines/xeen/spells.cpp | 573 ++++++++++++++++++++++++++++++++++++---- 5 files changed, 662 insertions(+), 45 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index dfc72aa4b1..f5357766ba 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -755,5 +755,112 @@ void NotWhileEngaged::execute(int spellId) { _vm->_mode = oldMode; } +/*------------------------------------------------------------------------*/ + +bool LloydsBeacon::show(XeenEngine *vm) { + LloydsBeacon *dlg = new LloydsBeacon(vm); + bool result = dlg->execute(); + delete dlg; + + return result; +} + +bool LloydsBeacon::execute() { + Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + Spells &spells = *_vm->_spells; + Window &w = screen._windows[10]; + bool isDarkCc = _vm->_files->_isDarkCc; + Character &c = *combat._oldCharacter; + + loadButtons(); + + if (!c._lloydMap) { + // No destination previously set, so have a default ready + if (isDarkCc) { + c._lloydSide = 1; + c._lloydPosition = Common::Point(25, 21); + c._lloydMap = 29; + } else { + c._lloydSide = 0; + c._lloydPosition = Common::Point(18, 4); + c._lloydMap = 28; + } + } + + // Open up the text file for the destination map and read in it's name + File textFile(Common::String::format("%s%c%03d.txt", + c._lloydSide == 0 ? "xeen" : "dark", + c._lloydMap >= 100 ? 'x' : '0', + c._lloydMap)); + Common::String mapName = textFile.readString(); + textFile.close(); + + // Display the dialog + w.open(); + w.writeString(Common::String::format(LLOYDS_BEACON, + mapName.c_str(), c._lloydPosition.x, c._lloydPosition.y)); + drawButtons(&screen); + w.update(); + + bool result = true; + do { + do { + events.updateGameCounter(); + intf.draw3d(true); + + do { + events.pollEventsAndWait(); + if (_vm->shouldQuit()) + return true; + + checkEvents(_vm); + } while (!_buttonValue && events.timeElapsed() < 1); + } while (!_buttonValue); + + switch (_buttonValue) { + case Common::KEYCODE_r: + if (!isDarkCc && c._lloydMap >= 75 && c._lloydMap <= 78 && !party._cloudsEnd) { + result = false; + } else { + sound.playFX(51); + map._loadDarkSide = isDarkCc; + if (c._lloydMap != party._mazeId || c._lloydSide != (isDarkCc ? 1 : 0)) { + map.load(c._lloydMap); + } + + party._mazePosition = c._lloydPosition; + } + + _buttonValue = Common::KEYCODE_ESCAPE; + break; + + case Common::KEYCODE_s: + case Common::KEYCODE_t: + sound.playFX(20); + c._lloydMap = party._mazeId; + c._lloydPosition = party._mazePosition; + c._lloydSide = isDarkCc ? 1 : 0; + + _buttonValue = Common::KEYCODE_ESCAPE; + break; + } + } while (_buttonValue != Common::KEYCODE_ESCAPE); + + w.close(); + return result; +} + +void LloydsBeacon::loadButtons() { + _iconSprites.load("lloyds.icn"); + + addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_r, &_iconSprites); + addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t, &_iconSprites); +} } // End of namespace Xeen diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h index b23f62b22f..ca7bb17b5e 100644 --- a/engines/xeen/dialogs_spells.h +++ b/engines/xeen/dialogs_spells.h @@ -109,6 +109,19 @@ public: static void show(XeenEngine *vm, int spellId); }; +class LloydsBeacon : public ButtonContainer { +private: + XeenEngine *_vm; + SpriteResource _iconSprites; + + LloydsBeacon(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + bool execute(); + + void loadButtons(); +public: + static bool show(XeenEngine *vm); +}; } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 228c5f6449..a75f77ba5c 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1544,4 +1544,14 @@ const char *const WHICH_ELEMENT2 = "\r\x3""cWhich Element?', 2, 0Bh, '034\t014\f15F\fdire\t044" "\f15E\fdlec\t074\f15C\fdold\t104\f15A\fdcid\x1"; +const char *const DETECT_MONSTERS = "\x3""cDetect Monsters"; + +const char *const LLOYDS_BEACON = + "\r\x3""c\v000\t000\x1Lloyd's Beacon\n" + "\n" + "Last Location\n" + "\n" + "%s\x3l\n" + "x = %d\x3r\t000y = %d\x3""c\x2\v122\t021\f15S\fdet\t060\f15R\fdeturn\x1"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 84a4648e84..89dc74a4fe 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -546,6 +546,10 @@ extern const char *const ON_WHO; extern const char *const WHICH_ELEMENT1; extern const char *const WHICH_ELEMENT2; +extern const char *const DETECT_MONSTERS; + +extern const char *const LLOYDS_BEACON; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index f5f6428b9f..e3978aef65 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -21,6 +21,7 @@ */ #include "xeen/spells.h" +#include "xeen/dialogs_items.h" #include "xeen/dialogs_spells.h" #include "xeen/files.h" #include "xeen/resources.h" @@ -258,7 +259,16 @@ void Spells::addSpellCost(Character &c, int spellId) { party._gems += gemCost; } -void Spells::acidSpray() { error("TODO: spell"); } +void Spells::acidSpray() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 15; + combat._damageType = DT_POISON; + combat._rangeType = RT_ALL; + sound.playFX(17); + combat.multiAttack(10); +} void Spells::awaken() { Interface &intf = *_vm->_interface; @@ -276,21 +286,106 @@ void Spells::awaken() { sound.playFX(30); } -void Spells::beastMaster() { error("TODO: spell"); } +void Spells::beastMaster() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; -void Spells::bless() { error("TODO: spell"); } + combat._monsterDamage = 0; + combat._damageType = DT_BEASTMASTER; + combat._rangeType = RT_GROUP; + sound.playFX(18); + combat.multiAttack(7); +} -void Spells::clairvoyance() { error("TODO: spell"); } +void Spells::bless() { + Combat &combat = *_vm->_combat; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; -void Spells::coldRay() { error("TODO: spell"); } + sound.playFX(30); + party._blessed = combat._oldCharacter->getCurrentLevel(); +} -void Spells::createFood() { error("TODO: spell"); } +void Spells::clairvoyance() { + _vm->_party->_clairvoyanceActive = true; + _vm->_sound->playFX(20); +} -void Spells::cureDisease() { error("TODO: spell"); } +void Spells::coldRay() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; -void Spells::cureParalysis() { error("TODO: spell"); } + combat._monsterDamage = _vm->getRandomNumber(2, 4) * combat._oldCharacter->getCurrentLevel(); + combat._damageType = DT_COLD; + combat._rangeType = RT_ALL; + sound.playFX(15); + combat.multiAttack(8); +} -void Spells::curePoison() { error("TODO: spell"); } +void Spells::createFood() { + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + party._food += party._activeParty.size(); + sound.playFX(20); +} + +void Spells::cureDisease() { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + int charIndex = SpellOnWho::show(_vm, MS_Revitalize); + if (charIndex == -1) + return; + + Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : + party._activeParty[charIndex]; + + sound.playFX(30); + c.addHitPoints(0); + c._conditions[DISEASED] = 0; + intf.drawParty(true); +} + +void Spells::cureParalysis() { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + int charIndex = SpellOnWho::show(_vm, MS_Revitalize); + if (charIndex == -1) + return; + + Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : + party._activeParty[charIndex]; + + sound.playFX(30); + c.addHitPoints(0); + c._conditions[PARALYZED] = 0; + intf.drawParty(true); +} + +void Spells::curePoison() { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + int charIndex = SpellOnWho::show(_vm, MS_Revitalize); + if (charIndex == -1) + return; + + Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : + party._activeParty[charIndex]; + + sound.playFX(30); + c.addHitPoints(0); + c._conditions[POISONED] = 0; + intf.drawParty(true); +} void Spells::cureWounds() { Combat &combat = *_vm->_combat; @@ -306,30 +401,178 @@ void Spells::cureWounds() { if (c.isDead()) { spellFailed(); - } - else { + } else { sound.playFX(30); c.addHitPoints(15); } } -void Spells::dancingSword() { error("TODO: spell"); } +void Spells::dancingSword() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = _vm->getRandomNumber(6, 14) * combat._oldCharacter->getCurrentLevel(); + combat._damageType = DT_PHYSICAL; + combat._rangeType = RT_GROUP; + sound.playFX(18); + combat.multiAttack(14); +} + +void Spells::dayOfProtection() { + Combat &combat = *_vm->_combat; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + int lvl = combat._oldCharacter->getCurrentLevel(); + party._walkOnWaterActive = true; + party._heroism = lvl; + party._holyBonus = lvl; + party._blessed = lvl; + party._poisonResistence = lvl; + party._coldResistence = lvl; + party._electricityResistence = lvl; + party._fireResistence = lvl; + party._lightCount = lvl; + sound.playFX(20); +} + +void Spells::dayOfSorcery() { + Combat &combat = *_vm->_combat; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + int lvl = combat._oldCharacter->getCurrentLevel(); + party._powerShield = lvl; + party._clairvoyanceActive = true; + party._wizardEyeActive = true; + party._levitateActive = true; + party._lightCount = lvl; + party._automapOn = false; + sound.playFX(20); +} + +void Spells::deadlySwarm() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 40; + combat._damageType = DT_PHYSICAL; + combat._rangeType = RT_GROUP; + sound.playFX(13); + combat.multiAttack(15); +} + +void Spells::detectMonster() { + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + Window &w = screen._windows[19]; + bool isDarkCc = _vm->_files->_isDarkCc; + int grid[7][7]; + + SpriteResource sprites(isDarkCc ? "detectmn.icn" : "detctmon.icn"); + Common::fill(&grid[0][0], &grid[7][7], 0); + + w.open(); + w.writeString(DETECT_MONSTERS); + sprites.draw(w, 0, Common::Point(243, 80)); + + for (int yDiff = 3; yDiff >= -3; --yDiff) { + for (int xDiff = -3; xDiff <= 3; ++xDiff) { + for (uint monIndex = 0; monIndex < map._mobData._monsters.size(); ++monIndex) { + MazeMonster &monster = map._mobData._monsters[monIndex]; + Common::Point pt = party._mazePosition + Common::Point(xDiff, yDiff); + if (monster._position == pt) { + if (++grid[yDiff][xDiff] > 3) + grid[yDiff][xDiff] = 3; + + sprites.draw(w, grid[yDiff][xDiff], Common::Point(xDiff * 9 + 244, + yDiff * 7 + 81)); + } + } + } + } + + sprites.draw(w, party._mazeDirection + 1, Common::Point(270, 101)); + sound.playFX(20); + w.update(); + + do { + events.updateGameCounter(); + intf.draw3d(true); + + events.wait(1); + } while (!events.isKeyMousePressed()); + + w.close(); +} + +void Spells::divineIntervention() { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + Character &castChar = *combat._oldCharacter; -void Spells::dayOfProtection() { error("TODO: spell"); } + if ((castChar._tempAge + 5) > 250) { + castChar._tempAge = 250; + } else { + castChar._tempAge += 5; + } -void Spells::dayOfSorcery() { error("TODO: spell"); } + for (uint idx = 0; idx < party._activeParty.size(); ++idx) { + Character &c = party._activeParty[idx]; + Common::fill(&c._conditions[CURSED], &c._conditions[ERADICATED], 0); + if (!c._conditions[ERADICATED]) + c._currentHp = c.getMaxHP(); + } -void Spells::deadlySwarm() { error("TODO: spell"); } + sound.playFX(20); + intf.drawParty(true); +} + +void Spells::dragonSleep() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 0; + combat._damageType = DT_DRAGONSLEEP; + combat._rangeType = RT_SINGLE; + sound.playFX(18); + combat.multiAttack(7); +} -void Spells::detectMonster() { error("TODO: spell"); } +void Spells::elementalStorm() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + static const int STORM_FX_LIST[4] = { 13, 14, 15, 17 }; + static const int STORM_MA_LIST[4] = { 0, 5, 9, 10 }; + + combat._monsterDamage = 150; + combat._damageType = (DamageType)_vm->getRandomNumber(DT_FIRE, DT_POISON); + combat._rangeType = RT_ALL; + sound.playFX(STORM_FX_LIST[combat._damageType]); + combat.multiAttack(STORM_MA_LIST[combat._damageType]); +} -void Spells::divineIntervention() { error("TODO: spell"); } +void Spells::enchantItem() { + Combat &combat = *_vm->_combat; + Party &party = *_vm->_party; + Mode oldMode = _vm->_mode; -void Spells::dragonSleep() { error("TODO: spell"); } + int charIndex = SpellOnWho::show(_vm, MS_FirstAid); + if (charIndex == -1) + return; -void Spells::elementalStorm() { error("TODO: spell"); } + Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : + party._activeParty[charIndex]; + ItemsDialog::show(_vm, &c, ITEMMODE_ENCHANT); -void Spells::enchantItem() { error("TODO: spell"); } + _vm->_mode = oldMode; +} void Spells::energyBlast() { Combat &combat = *_vm->_combat; @@ -342,15 +585,67 @@ void Spells::energyBlast() { combat.multiAttack(13); } -void Spells::etherialize() { error("TODO: spell"); } // Not while engaged +void Spells::etherialize() { + Map &map = *_vm->_map; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + Common::Point pt = party._mazePosition + Common::Point( + SCREEN_POSITIONING_X[party._mazeDirection][7], + SCREEN_POSITIONING_Y[party._mazeDirection][7] + ); -void Spells::fantasticFreeze() { error("TODO: spell"); } + if ((map.mazeData()._mazeFlags & RESTRICTION_ETHERIALIZE) || + map.mazeLookup(pt, 0, 0xffff) == INVALID_CELL) { + spellFailed(); + } else { + party._mazePosition = pt; + sound.playFX(51); + } +} -void Spells::fieryFlail() { error("TODO: spell"); } +void Spells::fantasticFreeze() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; -void Spells::fingerOfDeath() { error("TODO: spell"); } + combat._monsterDamage = 40; + combat._damageType = DT_COLD; + combat._rangeType = RT_GROUP; + sound.playFX(15); + combat.multiAttack(8); +} + +void Spells::fieryFlail() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 100; + combat._damageType = DT_FIRE; + combat._rangeType = RT_SINGLE; + sound.playFX(13); + combat.multiAttack(2); +} + +void Spells::fingerOfDeath() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; -void Spells::fireball() { error("TODO: spell"); } + combat._monsterDamage = 0; + combat._damageType = DT_FINGEROFDEATH; + combat._rangeType = RT_GROUP; + sound.playFX(18); + combat.multiAttack(14); +} + +void Spells::fireball() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = _vm->getRandomNumber(3, 7) * combat._oldCharacter->getCurrentLevel(); + combat._damageType = DT_FIRE; + combat._rangeType = RT_GROUP; + sound.playFX(13); + combat.multiAttack(0); +} void Spells::firstAid() { Combat &combat = *_vm->_combat; @@ -384,29 +679,132 @@ void Spells::flyingFist() { combat.multiAttack(14); } -void Spells::frostbite() { error("TODO: spell"); } +void Spells::frostbite() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; -void Spells::golemStopper() { error("TODO: spell"); } + combat._monsterDamage = 35; + combat._damageType = DT_COLD; + combat._rangeType = RT_SINGLE; + sound.playFX(8); + combat.multiAttack(8); +} -void Spells::heroism() { error("TODO: spell"); } +void Spells::golemStopper() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; -void Spells::holyBonus() { error("TODO: spell"); } + combat._monsterDamage = 0; + combat._damageType = DT_GOLEMSTOPPER; + combat._rangeType = RT_SINGLE; + sound.playFX(16); + combat.multiAttack(6); +} -void Spells::holyWord() { error("TODO: spell"); } +void Spells::heroism() { + Combat &combat = *_vm->_combat; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; -void Spells::hypnotize() { error("TODO: spell"); } + sound.playFX(30); + party._heroism = combat._oldCharacter->getCurrentLevel(); +} + +void Spells::holyBonus() { + Combat &combat = *_vm->_combat; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + sound.playFX(30); + party._holyBonus = combat._oldCharacter->getCurrentLevel(); +} + +void Spells::holyWord() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 0; + combat._damageType = DT_HOLYWORD; + combat._rangeType = RT_GROUP; + sound.playFX(18); + combat.multiAttack(13); +} + +void Spells::hypnotize() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 0; + combat._damageType = DT_HYPNOTIZE; + combat._rangeType = RT_GROUP; + sound.playFX(18); + combat.multiAttack(7); +} void Spells::identifyMonster() { error("TODO: spell"); } -void Spells::implosion() { error("TODO: spell"); } +void Spells::implosion() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; -void Spells::incinerate() { error("TODO: spell"); } + combat._monsterDamage = 1000; + combat._damageType = DT_ENERGY; + combat._rangeType = RT_SINGLE; + sound.playFX(18); + combat.multiAttack(6); +} -void Spells::inferno() { error("TODO: spell"); } +void Spells::incinerate() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; -void Spells::insectSpray() { error("TODO: spell"); } + combat._monsterDamage = 250; + combat._damageType = DT_FIRE; + combat._rangeType = RT_SINGLE; + sound.playFX(22); + combat.multiAttack(1); +} -void Spells::itemToGold() { error("TODO: spell"); } +void Spells::inferno() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 250; + combat._damageType = DT_FIRE; + combat._rangeType = RT_GROUP; + sound.playFX(13); + combat.multiAttack(1); +} + +void Spells::insectSpray() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 0; + combat._damageType = DT_INSECT_SPRAY; + combat._rangeType = RT_GROUP; + sound.playFX(17); + combat.multiAttack(10); +} + +void Spells::itemToGold() { + Combat &combat = *_vm->_combat; + Party &party = *_vm->_party; + + int charIndex = SpellOnWho::show(_vm, MS_Revitalize); + if (charIndex == -1) + return; + + Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : + party._activeParty[charIndex]; + Mode oldMode = _vm->_mode; + _vm->_mode = MODE_FF; + + _vm->_screen->_windows[11].close(); + ItemsDialog::show(_vm, &c, ITEMMODE_TO_GOLD); + + _vm->_mode = oldMode; +} void Spells::jump() { Map &map = *_vm->_map; @@ -446,7 +844,10 @@ void Spells::jump() { spellFailed(); } -void Spells::levitate() { error("TODO: spell"); } +void Spells::levitate() { + _vm->_party->_levitateActive = true; + _vm->_sound->playFX(20); +} void Spells::light() { Interface &intf = *_vm->_interface; @@ -459,9 +860,25 @@ void Spells::light() { sound.playFX(39); } -void Spells::lightningBolt() { error("TODO: spell"); } +void Spells::lightningBolt() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = _vm->getRandomNumber(4, 6) * combat._oldCharacter->getCurrentLevel(); + combat._damageType = DT_ELECTRICAL; + combat._rangeType = RT_GROUP; + sound.playFX(14); + combat.multiAttack(3); +} -void Spells::lloydsBeacon() { error("TODO: spell"); } // Not while engaged +void Spells::lloydsBeacon() { + if (_vm->_map->mazeData()._mazeFlags & RESTRICTION_LLOYDS_BEACON) { + spellFailed(); + } else { + if (!LloydsBeacon::show(_vm)) + spellFailed(); + } +} void Spells::magicArrow() { Combat &combat = *_vm->_combat; @@ -471,13 +888,68 @@ void Spells::magicArrow() { combat.multiAttack(11); } -void Spells::massDistortion() { error("TODO: spell"); } +void Spells::massDistortion() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 0; + combat._damageType = DT_MASS_DISTORTION; + combat._rangeType = RT_GROUP; + sound.playFX(18); + combat.multiAttack(6); +} + +void Spells::megaVolts() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 150; + combat._damageType = DT_ELECTRICAL; + combat._rangeType = RT_GROUP; + sound.playFX(14); + combat.multiAttack(4); +} + +void Spells::moonRay() { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 30; + combat._damageType = DT_ENERGY; + combat._rangeType = RT_ALL; + sound.playFX(16); + combat.multiAttack(13); + + for (uint idx = 0; idx < party._activeParty.size(); ++idx) { + sound.playFX(30); + party._activeParty[idx].addHitPoints(_vm->getRandomNumber(1, 30)); + } + + intf.drawParty(true); +} + +void Spells::naturesCure() { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; -void Spells::megaVolts() { error("TODO: spell"); } + int charIndex = SpellOnWho::show(_vm, MS_Revitalize); + if (charIndex == -1) + return; -void Spells::moonRay() { error("TODO: spell"); } + Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : + party._activeParty[charIndex]; -void Spells::naturesCure() { error("TODO: spell"); } + if (c.isDead()) { + spellFailed(); + } else { + sound.playFX(30); + c.addHitPoints(25); + } +} void Spells::pain() { Combat &combat = *_vm->_combat; @@ -490,9 +962,20 @@ void Spells::pain() { combat.multiAttack(14); } -void Spells::poisonVolley() { error("TODO: spell"); } +void Spells::poisonVolley() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 10; + combat._damageType = DT_POISON_VOLLEY; + combat._rangeType = RT_ALL; + sound.playFX(49); + combat.multiAttack(11); +} -void Spells::powerCure() { error("TODO: spell"); } +void Spells::powerCure() { + +} void Spells::powerShield() { error("TODO: spell"); } -- cgit v1.2.3 From c6506b567c791c6ef9a80df01f666c2c6d6d4b48 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 1 Mar 2015 10:07:03 -0500 Subject: XEEN: Implemented more spells --- engines/xeen/dialogs_spells.cpp | 116 +++++++++++- engines/xeen/dialogs_spells.h | 25 ++- engines/xeen/map.h | 2 +- engines/xeen/resources.cpp | 18 ++ engines/xeen/resources.h | 6 + engines/xeen/spells.cpp | 411 +++++++++++++++++++++++++++++----------- 6 files changed, 464 insertions(+), 114 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index f5357766ba..eb7373313e 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -21,6 +21,7 @@ */ #include "xeen/dialogs_spells.h" +#include "xeen/dialogs_input.h" #include "xeen/dialogs_query.h" #include "xeen/resources.h" #include "xeen/spells.h" @@ -579,12 +580,18 @@ void CastSpell::loadButtons() { /*------------------------------------------------------------------------*/ -int SpellOnWho::show(XeenEngine *vm, int spellId) { +Character *SpellOnWho::show(XeenEngine *vm, int spellId) { SpellOnWho *dlg = new SpellOnWho(vm); int result = dlg->execute(spellId); delete dlg; - return result; + if (result == -1) + return nullptr; + + Combat &combat = *vm->_combat; + Party &party = *vm->_party; + return combat._combatMode == 2 ? combat._combatParty[result] : + &party._activeParty[result]; } int SpellOnWho::execute(int spellId) { @@ -773,7 +780,6 @@ bool LloydsBeacon::execute() { Party &party = *_vm->_party; Screen &screen = *_vm->_screen; SoundManager &sound = *_vm->_sound; - Spells &spells = *_vm->_spells; Window &w = screen._windows[10]; bool isDarkCc = _vm->_files->_isDarkCc; Character &c = *combat._oldCharacter; @@ -863,4 +869,108 @@ void LloydsBeacon::loadButtons() { addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t, &_iconSprites); } +/*------------------------------------------------------------------------*/ + +int Teleport::show(XeenEngine *vm) { + Teleport *dlg = new Teleport(vm); + int result = dlg->execute(); + delete dlg; + + return result; +} + +int Teleport::execute() { + Map &map = *_vm->_map; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + Window &w = screen._windows[6]; + Common::String num; + + w.open(); + w.writeString(Common::String::format(HOW_MANY_SQUARES, + DIRECTION_TEXT[party._mazeDirection])); + w.update(); + int lineSize = Input::show(_vm, &w, num, 1, 200, true); + w.close(); + + if (!lineSize) + return -1; + int numSquares = atoi(num.c_str()); + Common::Point pt = party._mazePosition; + int v; + + switch (party._mazeDirection) { + case DIR_NORTH: + pt.y += numSquares; + break; + case DIR_EAST: + pt.x += numSquares; + break; + case DIR_SOUTH: + pt.y -= numSquares; + break; + case DIR_WEST: + pt.x -= numSquares; + break; + } + + v = map.mazeLookup(pt, map._isOutdoors ? 0xF : 0xFFFF, 0); + + if ((v != (map._isOutdoors ? 0 : INVALID_CELL)) && + (!map._isOutdoors || v == SURFTYPE_DWATER)) { + party._mazePosition = pt; + return 1; + } else { + return 0; + } +} + +/*------------------------------------------------------------------------*/ + +int TownPortal::show(XeenEngine *vm) { + TownPortal *dlg = new TownPortal(vm); + int townNumber = dlg->execute(); + delete dlg; + + return townNumber; +} + +int TownPortal::execute() { + Map &map = *_vm->_map; + Screen &screen = *_vm->_screen; + Window &w = screen._windows[20]; + Common::String townNames[5]; + Mode oldMode = _vm->_mode; + _vm->_mode = MODE_FF; + + // Build up a lsit of the names of the towns on the current side of Xeen + for (int idx = 0; idx < 5; ++idx) { + File f(Common::String::format("%s%04d.txt", + map._sideTownPortal ? "dark" : "xeen", + TOWN_MAP_NUMBERS[map._sideTownPortal][idx])); + townNames[idx] = f.readString(); + f.close(); + } + + w.open(); + w.writeString(Common::String::format(TOWN_PORTAL, + townNames[0].c_str(), townNames[1].c_str(), townNames[2].c_str(), + townNames[3].c_str(), townNames[4].c_str() + )); + w.update(); + + // Get the town number + int townNumber; + Common::String num; + do { + int result = Input::show(_vm, &w, num, 1, 160, true); + townNumber = !result ? 0 : atoi(num.c_str()); + } while (townNumber > 5); + + w.close(); + _vm->_mode = oldMode; + + return townNumber; +} + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h index ca7bb17b5e..9f4af15636 100644 --- a/engines/xeen/dialogs_spells.h +++ b/engines/xeen/dialogs_spells.h @@ -81,7 +81,7 @@ private: int execute(int spellId); public: - static int show(XeenEngine *vm, int spellId); + static Character *show(XeenEngine *vm, int spellId); }; class SelectElement : public ButtonContainer { @@ -123,6 +123,29 @@ public: static bool show(XeenEngine *vm); }; +class Teleport : public ButtonContainer { +private: + XeenEngine *_vm; + SpriteResource _iconSprites; + + Teleport(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + int execute(); +public: + static int show(XeenEngine *vm); +}; + +class TownPortal : public ButtonContainer { +private: + XeenEngine *_vm; + + TownPortal(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + int execute(); +public: + static int show(XeenEngine *vm); +}; + } // End of namespace Xeen #endif /* XEEN_DIALOGS_SPELLS_H */ diff --git a/engines/xeen/map.h b/engines/xeen/map.h index bfc09ec053..a7e88c1726 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -356,7 +356,6 @@ private: XeenEngine *_vm; MazeData _mazeData[9]; SpriteResource _wallPicSprites; - int _sideTownPortal; int _sidePictures; int _sideObjects; int _sideMonsters; @@ -387,6 +386,7 @@ public: int _currentSurfaceId; bool _currentSteppedOn; bool _loadDarkSide; + int _sideTownPortal; public: Map(XeenEngine *vm); diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index a75f77ba5c..085cfab58d 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1554,4 +1554,22 @@ const char *const LLOYDS_BEACON = "%s\x3l\n" "x = %d\x3r\t000y = %d\x3""c\x2\v122\t021\f15S\fdet\t060\f15R\fdeturn\x1"; +const char *const HOW_MANY_SQUARES = "\x03cTeleport\nHow many squares %s (1-9)"; + +const char *const TOWN_PORTAL = + "\x3""cTown Portal\x3l\n" + "\n" + "\t0101. %s\n" + "\t0102. %s\n" + "\t0103. %s\n" + "\t0104. %s\n" + "\t0105. %s\x3""c\n" + "\n" + "To which Town (1-5)\n" + "\n"; + +const int TOWN_MAP_NUMBERS[2][5] = { + { 28, 29, 30, 31, 32 }, { 29, 31, 33, 35, 37 } +}; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 89dc74a4fe..29e86112a1 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -550,6 +550,12 @@ extern const char *const DETECT_MONSTERS; extern const char *const LLOYDS_BEACON; +extern const char *const HOW_MANY_SQUARES; + +extern const char *const TOWN_PORTAL; + +extern const int TOWN_MAP_NUMBERS[2][5]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index e3978aef65..e2e8cfde36 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -331,79 +331,59 @@ void Spells::createFood() { } void Spells::cureDisease() { - Combat &combat = *_vm->_combat; Interface &intf = *_vm->_interface; - Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; - int charIndex = SpellOnWho::show(_vm, MS_Revitalize); - if (charIndex == -1) + Character *c = SpellOnWho::show(_vm, MS_CureDisease); + if (!c) return; - Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : - party._activeParty[charIndex]; - sound.playFX(30); - c.addHitPoints(0); - c._conditions[DISEASED] = 0; + c->addHitPoints(0); + c->_conditions[DISEASED] = 0; intf.drawParty(true); } void Spells::cureParalysis() { - Combat &combat = *_vm->_combat; Interface &intf = *_vm->_interface; - Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; - int charIndex = SpellOnWho::show(_vm, MS_Revitalize); - if (charIndex == -1) + Character *c = SpellOnWho::show(_vm, MS_CureParalysis); + if (!c) return; - Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : - party._activeParty[charIndex]; - sound.playFX(30); - c.addHitPoints(0); - c._conditions[PARALYZED] = 0; + c->addHitPoints(0); + c->_conditions[PARALYZED] = 0; intf.drawParty(true); } void Spells::curePoison() { - Combat &combat = *_vm->_combat; Interface &intf = *_vm->_interface; - Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; - int charIndex = SpellOnWho::show(_vm, MS_Revitalize); - if (charIndex == -1) + Character *c = SpellOnWho::show(_vm, MS_CurePoison); + if (!c) return; - Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : - party._activeParty[charIndex]; - sound.playFX(30); - c.addHitPoints(0); - c._conditions[POISONED] = 0; + c->addHitPoints(0); + c->_conditions[POISONED] = 0; intf.drawParty(true); } void Spells::cureWounds() { - Combat &combat = *_vm->_combat; - Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; - int charIndex = SpellOnWho::show(_vm, MS_Revitalize); - if (charIndex == -1) + Character *c = SpellOnWho::show(_vm, MS_CureWounds); + if (!c) return; - Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : - party._activeParty[charIndex]; - - if (c.isDead()) { + if (c->isDead()) { spellFailed(); } else { sound.playFX(30); - c.addHitPoints(15); + c->addHitPoints(15); } } @@ -559,17 +539,13 @@ void Spells::elementalStorm() { } void Spells::enchantItem() { - Combat &combat = *_vm->_combat; - Party &party = *_vm->_party; Mode oldMode = _vm->_mode; - int charIndex = SpellOnWho::show(_vm, MS_FirstAid); - if (charIndex == -1) + Character *c = SpellOnWho::show(_vm, MS_EnchantItem); + if (!c) return; - Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : - party._activeParty[charIndex]; - ItemsDialog::show(_vm, &c, ITEMMODE_ENCHANT); + ItemsDialog::show(_vm, c, ITEMMODE_ENCHANT); _vm->_mode = oldMode; } @@ -648,23 +624,17 @@ void Spells::fireball() { } void Spells::firstAid() { - Combat &combat = *_vm->_combat; - Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; - int charIndex = SpellOnWho::show(_vm, MS_FirstAid); - if (charIndex == -1) + Character *c = SpellOnWho::show(_vm, MS_FirstAid); + if (!c) return; - Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : - party._activeParty[charIndex]; - - if (c.isDead()) { + if (c->isDead()) { spellFailed(); - } - else { + } else { sound.playFX(30); - c.addHitPoints(6); + c->addHitPoints(6); } } @@ -788,20 +758,15 @@ void Spells::insectSpray() { } void Spells::itemToGold() { - Combat &combat = *_vm->_combat; - Party &party = *_vm->_party; - - int charIndex = SpellOnWho::show(_vm, MS_Revitalize); - if (charIndex == -1) + Character *c = SpellOnWho::show(_vm, MS_ItemToGold); + if (!c) return; - Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : - party._activeParty[charIndex]; Mode oldMode = _vm->_mode; _vm->_mode = MODE_FF; _vm->_screen->_windows[11].close(); - ItemsDialog::show(_vm, &c, ITEMMODE_TO_GOLD); + ItemsDialog::show(_vm, c, ITEMMODE_TO_GOLD); _vm->_mode = oldMode; } @@ -931,23 +896,17 @@ void Spells::moonRay() { } void Spells::naturesCure() { - Combat &combat = *_vm->_combat; - Interface &intf = *_vm->_interface; - Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; - int charIndex = SpellOnWho::show(_vm, MS_Revitalize); - if (charIndex == -1) + Character *c = SpellOnWho::show(_vm, MS_NaturesCure); + if (!c) return; - Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : - party._activeParty[charIndex]; - - if (c.isDead()) { + if (c->isDead()) { spellFailed(); } else { sound.playFX(30); - c.addHitPoints(25); + c->addHitPoints(25); } } @@ -974,12 +933,39 @@ void Spells::poisonVolley() { } void Spells::powerCure() { - + SoundManager &sound = *_vm->_sound; + + Character *c = SpellOnWho::show(_vm, MS_PowerCure); + if (!c) + return; + + if (c->isDead()) { + spellFailed(); + } else { + sound.playFX(30); + c->addHitPoints(_vm->getRandomNumber(2, 12) * _vm->_combat->_oldCharacter->getCurrentLevel()); + } +} + +void Spells::powerShield() { + Combat &combat = *_vm->_combat; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + sound.playFX(20); + party._powerShield = combat._oldCharacter->getCurrentLevel(); } -void Spells::powerShield() { error("TODO: spell"); } +void Spells::prismaticLight() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; -void Spells::prismaticLight() { error("TODO: spell"); } + combat._monsterDamage = 80; + combat._damageType = (DamageType)_vm->getRandomNumber(DT_PHYSICAL, DT_ENERGY); + combat._rangeType = RT_ALL; + sound.playFX(18); + combat.multiAttack(14); +} void Spells::protectionFromElements() { Combat &combat = *_vm->_combat; @@ -1013,32 +999,91 @@ void Spells::protectionFromElements() { } } -void Spells::raiseDead() { error("TODO: spell"); } +void Spells::raiseDead() { + Interface &intf = *_vm->_interface; + SoundManager &sound = *_vm->_sound; -void Spells::rechargeItem() { error("TODO: spell"); } + Character *c = SpellOnWho::show(_vm, MS_RaiseDead); + if (!c) + return; -void Spells::resurrection() { error("TODO: spell"); } + if (!c->_conditions[DEAD]) { + spellFailed(); + } else { + c->_conditions[DEAD] = 0; + c->_conditions[UNCONSCIOUS] = 0; + c->_currentHp = 0; + sound.playFX(30); + c->addHitPoints(1); + if (--c->_endurance._permanent < 1) + c->_endurance._permanent = 1; -void Spells::revitalize() { - Combat &combat = *_vm->_combat; + intf.drawParty(true); + } +} + +void Spells::rechargeItem() { + Mode oldMode = _vm->_mode; + + Character *c = SpellOnWho::show(_vm, MS_RechargeItem); + if (!c) + return; + + ItemsDialog::show(_vm, c, ITEMMODE_RECHARGE); + _vm->_mode = oldMode; +} + +void Spells::resurrection() { Interface &intf = *_vm->_interface; - Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; - int charIndex = SpellOnWho::show(_vm, MS_Revitalize); - if (charIndex == -1) + Character *c = SpellOnWho::show(_vm, MS_RaiseDead); + if (!c) return; - Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : - party._activeParty[charIndex]; + if (!c->_conditions[ERADICATED]) { + spellFailed(); + sound.playFX(30); + } else { + sound.playFX(30); + c->addHitPoints(0); + c->_conditions[ERADICATED] = 0; + + if (--c->_endurance._permanent < 1) + c->_endurance._permanent = 1; + if ((c->_tempAge + 5) >= 250) + c->_tempAge = 250; + else + c->_tempAge += 5; + + intf.drawParty(true); + } +} + +void Spells::revitalize() { + Interface &intf = *_vm->_interface; + SoundManager &sound = *_vm->_sound; + + Character *c = SpellOnWho::show(_vm, MS_Revitalize); + if (!c) + return; sound.playFX(30); - c.addHitPoints(0); - c._conditions[WEAK] = 0; + c->addHitPoints(0); + c->_conditions[WEAK] = 0; intf.drawParty(true); } -void Spells::shrapMetal() { error("TODO: spell"); } +void Spells::shrapMetal() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2; + combat._damageType = DT_PHYSICAL; + combat._rangeType = RT_GROUP; + sound.playFX(16); + combat.multiAttack(15); +} void Spells::sleep() { Combat &combat = *_vm->_combat; @@ -1062,47 +1107,182 @@ void Spells::sparks() { combat.multiAttack(5); } -void Spells::starBurst() { error("TODO: spell"); } +void Spells::starBurst() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; -void Spells::stoneToFlesh() { error("TODO: spell"); } + combat._monsterDamage = 500; + combat._damageType = DT_FIRE; + combat._rangeType = RT_ALL; + sound.playFX(13); + combat.multiAttack(15); +} -void Spells::sunRay() { error("TODO: spell"); } +void Spells::stoneToFlesh() { + Interface &intf = *_vm->_interface; + SoundManager &sound = *_vm->_sound; -void Spells::superShelter() { error("TODO: spell"); } + Character *c = SpellOnWho::show(_vm, MS_StoneToFlesh); + if (!c) + return; -void Spells::suppressDisease() { error("TODO: spell"); } + sound.playFX(30); + c->addHitPoints(0); + c->_conditions[STONED] = 0; + intf.drawParty(true); +} -void Spells::suppressPoison() { +void Spells::sunRay() { Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 200; + combat._damageType = DT_ENERGY; + combat._rangeType = RT_ALL; + sound.playFX(16); + combat.multiAttack(13); +} + +void Spells::superShelter() { Interface &intf = *_vm->_interface; - Party &party = *_vm->_party; + Map &map = *_vm->_map; SoundManager &sound = *_vm->_sound; - int charIndex = SpellOnWho::show(_vm, MS_FirstAid); - if (charIndex == -1) + if (map.mazeData()._mazeFlags & RESTRICTION_SUPER_SHELTER) { + spellFailed(); + } else { + Mode oldMode = _vm->_mode; + _vm->_mode = MODE_12; + sound.playFX(30); + intf.rest(); + _vm->_mode = oldMode; + } +} + +void Spells::suppressDisease() { + Interface &intf = *_vm->_interface; + SoundManager &sound = *_vm->_sound; + + Character *c = SpellOnWho::show(_vm, MS_SuppressDisease); + if (!c) return; - Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : - party._activeParty[charIndex]; + if (c->_conditions[DISEASED]) { + if (c->_conditions[DISEASED] >= 4) + c->_conditions[DISEASED] -= 3; + else + c->_conditions[DISEASED] = 1; + + sound.playFX(20); + c->addHitPoints(0); + intf.drawParty(true); + } +} + +void Spells::suppressPoison() { + Interface &intf = *_vm->_interface; + SoundManager &sound = *_vm->_sound; + + Character *c = SpellOnWho::show(_vm, MS_FirstAid); + if (!c) + return; - if (c._conditions[POISONED]) { - if (c._conditions[POISONED] >= 4) { - c._conditions[POISONED] -= 2; + if (c->_conditions[POISONED]) { + if (c->_conditions[POISONED] >= 4) { + c->_conditions[POISONED] -= 2; } else { - c._conditions[POISONED] = 1; + c->_conditions[POISONED] = 1; } } sound.playFX(20); - c.addHitPoints(0); + c->addHitPoints(0); intf.drawParty(1); } -void Spells::teleport() { error("TODO: spell"); } // Not while engaged +void Spells::teleport() { + Map &map = *_vm->_map; + SoundManager &sound = *_vm->_sound; -void Spells::timeDistortion() { error("TODO: spell"); } + if (map.mazeData()._mazeFlags & RESTRICTION_TELPORT) { + spellFailed(); + } else { + switch (Teleport::show(_vm)) { + case 0: + spellFailed(); + break; + case 1: + sound.playFX(51); + break; + default: + break; + } + } +} + +void Spells::timeDistortion() { + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + if (map.mazeData()._mazeFlags & RESTRICTION_TIME_DISTORTION) { + spellFailed(); + } else { + party.moveToRunLocation(); + sound.playFX(51); + intf.draw3d(true); + } +} + +void Spells::townPortal() { + Map &map = *_vm->_map; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + if (map.mazeData()._mazeFlags & RESTRICTION_TOWN_PORTAL) { + spellFailed(); + return; + } + + int townNumber = TownPortal::show(_vm); + if (!townNumber) + return; + + sound.playFX(51); + map._loadDarkSide = map._sideTownPortal; + _vm->_files->_isDarkCc = map._sideTownPortal > 0; + map.load(TOWN_MAP_NUMBERS[map._sideTownPortal][townNumber - 1]); -void Spells::townPortal() { error("TODO: spell"); } // Not while engaged + if (!_vm->_files->_isDarkCc) { + party.moveToRunLocation(); + } else { + switch (townNumber) { + case 1: + party._mazePosition = Common::Point(14, 11); + party._mazeDirection = DIR_SOUTH; + break; + case 2: + party._mazePosition = Common::Point(5, 12); + party._mazeDirection = DIR_WEST; + break; + case 3: + party._mazePosition = Common::Point(2, 15); + party._mazeDirection = DIR_EAST; + break; + case 4: + party._mazePosition = Common::Point(8, 11); + party._mazeDirection = DIR_NORTH; + break; + case 5: + party._mazePosition = Common::Point(2, 6); + party._mazeDirection = DIR_NORTH; + break; + default: + break; + } + } +} void Spells::toxicCloud() { Combat &combat = *_vm->_combat; @@ -1126,9 +1306,22 @@ void Spells::turnUndead() { combat.multiAttack(13); } -void Spells::walkOnWater() { error("TODO: spell"); } +void Spells::walkOnWater() { + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + party._walkOnWaterActive = true; + sound.playFX(20); +} + +void Spells::wizardEye() { + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; -void Spells::wizardEye() { error("TODO: spell"); } // Not while engaged + party._wizardEyeActive = true; + party._automapOn = false; + sound.playFX(20); +} void Spells::frostbite2() { Combat &combat = *_vm->_combat; -- cgit v1.2.3 From ee5b8ed59f1aaa00767ac3805d7ab63dd5a5f5d4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 1 Mar 2015 10:41:11 -0500 Subject: XEEN: Implement remaining spells --- engines/xeen/dialogs_spells.cpp | 52 +++++++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_spells.h | 11 +++++++++ engines/xeen/resources.cpp | 13 +++++++++++ engines/xeen/resources.h | 6 +++++ engines/xeen/spells.cpp | 11 ++++++++- engines/xeen/xeen.cpp | 5 ++++ engines/xeen/xeen.h | 2 ++ 7 files changed, 99 insertions(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index eb7373313e..f49dca66b1 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -973,4 +973,56 @@ int TownPortal::execute() { return townNumber; } +/*------------------------------------------------------------------------*/ + +void IdentifyMonster::show(XeenEngine *vm) { + IdentifyMonster *dlg = new IdentifyMonster(vm); + dlg->execute(); + delete dlg; +} + +void IdentifyMonster::execute() { + Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + Spells &spells = *_vm->_spells; + Window &w = screen._windows[17]; + Common::String monsterDesc[3]; + + for (int monIndex = 0; monIndex < 3; ++monIndex) { + if (combat._attackMonsters[monIndex] == -1) + continue; + + MazeMonster &monster = map._mobData._monsters[combat._attackMonsters[monIndex]]; + MonsterStruct &monsterData = *monster._monsterData; + + monsterDesc[monIndex] = Common::String::format(MONSTER_DETAILS, + monsterData._name.c_str(), + _vm->printK2(monster._hp).c_str(), + monsterData._accuracy, monsterData._numberOfAttacks, + MONSTER_SPECIAL_ATTACKS[monsterData._specialAttack] + ); + } + + sound.playFX(20); + w.open(); + w.writeString(Common::String::format(IDENTIFY_MONSTERS, + monsterDesc[0].c_str(), monsterDesc[1].c_str(), monsterDesc[2].c_str())); + w.update(); + + do { + events.updateGameCounter(); + intf.draw3d(false); + w.frame(); + screen._windows[3].update(); + + events.wait(1); + } while (!events.isKeyMousePressed()); + + w.close(); +} + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h index 9f4af15636..35b2708f7a 100644 --- a/engines/xeen/dialogs_spells.h +++ b/engines/xeen/dialogs_spells.h @@ -146,6 +146,17 @@ public: static int show(XeenEngine *vm); }; +class IdentifyMonster : public ButtonContainer { +private: + XeenEngine *_vm; + + IdentifyMonster(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + void execute(); +public: + static void show(XeenEngine *vm); +}; + } // End of namespace Xeen #endif /* XEEN_DIALOGS_SPELLS_H */ diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 085cfab58d..8bc99f6579 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1572,4 +1572,17 @@ const int TOWN_MAP_NUMBERS[2][5] = { { 28, 29, 30, 31, 32 }, { 29, 31, 33, 35, 37 } }; +const char *const MONSTER_DETAILS = + "\x3l\n" + "%s\x3""c\t100%s\t140%u\t180%u\x3r\t000%s"; + +const char *const MONSTER_SPECIAL_ATTACKS[23] = { + "None", "Magic", "Fire", "Elec", "Cold", "Poison", "Energy", "Disease", + "Insane", "Asleep", "CurseItm", "InLove", "DrnSPts", "Curse", "Paralys", + "Uncons", "Confuse", "BrkWpn", "Weak", "Erad", "Age+5", "Dead", "Stone" +}; + +const char *const IDENTIFY_MONSTERS = + "Name\x3""c\t100HP\t140AC\t177#Atks\x3r\t000Special%s%s%s"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 29e86112a1..e15c509391 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -556,6 +556,12 @@ extern const char *const TOWN_PORTAL; extern const int TOWN_MAP_NUMBERS[2][5]; +extern const char *const MONSTER_DETAILS; + +extern const char *const MONSTER_SPECIAL_ATTACKS[23]; + +extern const char *const IDENTIFY_MONSTERS; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index e2e8cfde36..ba4e78bfb9 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -711,7 +711,16 @@ void Spells::hypnotize() { combat.multiAttack(7); } -void Spells::identifyMonster() { error("TODO: spell"); } +void Spells::identifyMonster() { + Combat &combat = *_vm->_combat; + + if (combat._attackMonsters[0] == -1 && combat._attackMonsters[1] == -1 + && combat._attackMonsters[2] == -1) { + spellFailed(); + } else { + IdentifyMonster::show(_vm); + } +} void Spells::implosion() { Combat &combat = *_vm->_combat; diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index a1604a5eab..fb7edead00 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -350,4 +350,9 @@ Common::String XeenEngine::printK(uint value) { Common::String::format("%u", value); } +Common::String XeenEngine::printK2(uint value) { + return (value > 999) ? Common::String::format("%uk", value / 1000) : + Common::String::format("%u", value); +} + } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 2d995a1dd3..71859413aa 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -203,6 +203,8 @@ public: static Common::String printMil(uint value); static Common::String printK(uint value); + + static Common::String printK2(uint value); }; } // End of namespace Xeen -- cgit v1.2.3 From 8e6708e6008b3ac1132f84923ebc766d1b199679 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 1 Mar 2015 21:58:58 -0500 Subject: XEEN: Hook up debugger properly and implement spell command --- engines/xeen/debugger.cpp | 35 +++++++++++++++++++++++++++++++---- engines/xeen/debugger.h | 7 +++++-- engines/xeen/dialogs_error.cpp | 5 ++++- engines/xeen/dialogs_spells.cpp | 1 - engines/xeen/events.cpp | 14 +++++++++++++- engines/xeen/resources.cpp | 16 ++++++++-------- 6 files changed, 61 insertions(+), 17 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/debugger.cpp b/engines/xeen/debugger.cpp index a83af9f99d..35cbaeb58c 100644 --- a/engines/xeen/debugger.cpp +++ b/engines/xeen/debugger.cpp @@ -25,7 +25,7 @@ #include "xeen/debugger.h" namespace Xeen { -/* + static int strToInt(const char *s) { if (!*s) // No string at all @@ -41,16 +41,43 @@ static int strToInt(const char *s) { error("strToInt failed on string \"%s\"", s); return (int)tmp; } -*/ /*------------------------------------------------------------------------*/ Debugger::Debugger(XeenEngine *vm) : GUI::Debugger(), _vm(vm) { registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); - registerCmd("scene", WRAP_METHOD(Debugger, Cmd_LoadScene)); + registerCmd("spell", WRAP_METHOD(Debugger, cmdSpell)); + + _spellId = -1; } -bool Debugger::Cmd_LoadScene(int argc, const char **argv) { +void Debugger::update() { + Combat &combat = *_vm->_combat; + Party &party = *_vm->_party; + Spells &spells = *_vm->_spells; + + if (_spellId != -1) { + // Cast any specified spell + MagicSpell spellId = (MagicSpell)_spellId; + _spellId = -1; + spells.castSpell(&party._activeParty[0], spellId); + } + + onFrame(); +} + +bool Debugger::cmdSpell(int argc, const char **argv) { + if (argc != 2) { + debugPrintf("Format: spell <spell-id>"); + return true; + } else { + int spellId = strToInt(argv[1]); + if (spellId >= MS_AcidSpray && spellId <= MS_WizardEye) { + _spellId = spellId; + return false; + } + } + return true; } diff --git a/engines/xeen/debugger.h b/engines/xeen/debugger.h index 6a1ec12e80..e7f8ef6b7d 100644 --- a/engines/xeen/debugger.h +++ b/engines/xeen/debugger.h @@ -31,12 +31,15 @@ namespace Xeen { class XeenEngine; class Debugger : public GUI::Debugger { -protected: +private: XeenEngine *_vm; + int _spellId; - bool Cmd_LoadScene(int argc, const char **argv); + bool cmdSpell(int argc, const char **argv); public: Debugger(XeenEngine *vm); + + void update(); }; } // End of namespace Xeen diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp index 7f649afd86..7204bad8fe 100644 --- a/engines/xeen/dialogs_error.cpp +++ b/engines/xeen/dialogs_error.cpp @@ -93,6 +93,7 @@ void CantCast::show(XeenEngine *vm, int spellId, int componentNum) { void CantCast::execute(int spellId, int componentNum) { EventsManager &events = *_vm->_events; SoundManager &sound = *_vm->_sound; + Spells &spells = *_vm->_spells; Window &w = _vm->_screen->_windows[6]; Mode oldMode = _vm->_mode; _vm->_mode = MODE_FF; @@ -100,7 +101,9 @@ void CantCast::execute(int spellId, int componentNum) { sound.playFX(21); w.open(); w.writeString(Common::String::format(NOT_ENOUGH_TO_CAST, - SPELL_CAST_COMPONENTS[componentNum - 1])); + SPELL_CAST_COMPONENTS[componentNum - 1], + spells._spellNames[spellId].c_str() + )); w.update(); do { diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index f49dca66b1..7cde5f37ef 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -988,7 +988,6 @@ void IdentifyMonster::execute() { Map &map = *_vm->_map; Screen &screen = *_vm->_screen; SoundManager &sound = *_vm->_sound; - Spells &spells = *_vm->_spells; Window &w = screen._windows[17]; Common::String monsterDesc[3]; diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp index 9f13861dd2..92dc8b487f 100644 --- a/engines/xeen/events.cpp +++ b/engines/xeen/events.cpp @@ -94,7 +94,14 @@ void EventsManager::pollEvents() { case Common::EVENT_RTL: return; case Common::EVENT_KEYDOWN: - _keyCode = event.kbd.keycode; + // Check for debugger + if (event.kbd.keycode == Common::KEYCODE_d && (event.kbd.flags & Common::KBD_CTRL)) { + // Attach to the debugger + _vm->_debugger->attach(); + _vm->_debugger->onFrame(); + } else { + _keyCode = event.kbd.keycode; + } break; case Common::EVENT_MOUSEMOVE: _mousePos = event.mouse; @@ -181,6 +188,11 @@ void EventsManager::ipause(uint amount) { */ void EventsManager::nextFrame() { ++_frameCounter; + + // Allow debugger to update + _vm->_debugger->update(); + + // Update the screen _vm->_screen->update(); } diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 8bc99f6579..544db24385 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1315,7 +1315,7 @@ const char *const USE_ITEM_IN_COMBAT = const char *const NO_SPECIAL_ABILITIES = "\v005\x3""c%s\fdhas no special abilities!"; -const char *const CANT_CAST_WHILE_ENGAGED = "\x03c\v007Can't cast %s while engaged!"; +const char *const CANT_CAST_WHILE_ENGAGED = "\x3""c\v007Can't cast %s while engaged!"; const char *const EQUIPPED_ALL_YOU_CAN = "\x3""c\v007You have equipped all the %ss you can!"; const char *const REMOVE_X_TO_EQUIP_Y = "\x3""c\v007You must remove %sto equip %s\x8!"; @@ -1328,7 +1328,7 @@ const char *const CANNOT_DISCARD_CURSED_ITEM = "\3x""cYou cannot discard a curse const char *const PERMANENTLY_DISCARD = "\v000\t000\x03lPermanently discard %s\fd?"; -const char *const BACKPACK_IS_FULL = "\v005\x03c\fd%s's backpack is full."; +const char *const BACKPACK_IS_FULL = "\v005\x3""c\fd%s's backpack is full."; const char *const CATEGORY_BACKPACK_IS_FULL[4] = { "\v010\t000\x3""c%s's weapons backpack is full.", @@ -1341,11 +1341,11 @@ const char *const BUY_X_FOR_Y_GOLD = "\x3l\v000\t000\fdBuy %s\fd for %lu gold?"; const char *const SELL_X_FOR_Y_GOLD = "\x3l\v000\t000\fdSell %s\fd for %lu gold?"; -const char *const NO_NEED_OF_THIS = "\v005\x03c\fdWe have no need of this %s\f!"; +const char *const NO_NEED_OF_THIS = "\v005\x3""c\fdWe have no need of this %s\f!"; -const char *const NOT_RECHARGABLE = "\v012\x03c\fdNot Rechargeable. %s"; +const char *const NOT_RECHARGABLE = "\v012\x3""c\fdNot Rechargeable. %s"; -const char *const NOT_ENCHANTABLE = "\v012\t000\x03cNot Enchantable. %s"; +const char *const NOT_ENCHANTABLE = "\v012\t000\x3""cNot Enchantable. %s"; const char *const SPELL_FAILED = "Spell Failed!"; @@ -1495,7 +1495,7 @@ const int NEW_CHARACTER_SPELLS[10][4] = { const char *const COMBAT_DETAILS = "\r\f00\x3""c\v000\t000\x2""Combat%s%s%s\x1"; -const char *NOT_ENOUGH_TO_CAST = "\x03c\v010Not enough %s to Cast %s"; +const char *NOT_ENOUGH_TO_CAST = "\x3""c\v010Not enough %s to Cast %s"; const char *SPELL_CAST_COMPONENTS[2] = { "Spell Points", "Gems" }; const char *const CAST_SPELL_DETAILS = @@ -1530,7 +1530,7 @@ const char *const GIVE_TREASURE_FORMATTING = "\x4""077\n" "\x4""077"; -const char *const X_FOUND_Y = "\v060\t000\x03c%s found: %s"; +const char *const X_FOUND_Y = "\v060\t000\x3""c%s found: %s"; const char *const ON_WHO = "\x3""c\v009On Who?"; @@ -1554,7 +1554,7 @@ const char *const LLOYDS_BEACON = "%s\x3l\n" "x = %d\x3r\t000y = %d\x3""c\x2\v122\t021\f15S\fdet\t060\f15R\fdeturn\x1"; -const char *const HOW_MANY_SQUARES = "\x03cTeleport\nHow many squares %s (1-9)"; +const char *const HOW_MANY_SQUARES = "\x3""cTeleport\nHow many squares %s (1-9)"; const char *const TOWN_PORTAL = "\x3""cTown Portal\x3l\n" -- cgit v1.2.3 From 02c046941b76b5289d206bdc110cf55719a05dbb Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 1 Mar 2015 22:16:51 -0500 Subject: XEEN: Fixes for text entry --- engines/xeen/dialogs_input.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_input.cpp b/engines/xeen/dialogs_input.cpp index 042fabf102..3626441c7c 100644 --- a/engines/xeen/dialogs_input.cpp +++ b/engines/xeen/dialogs_input.cpp @@ -40,26 +40,35 @@ int Input::show(XeenEngine *vm, Window *window, Common::String &line, */ int Input::getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric) { _vm->_noDirectionSense = true; - Common::String msg = Common::String::format("\x03""l\t000\x04%03d\x03""c", maxWidth); + Common::String msg = Common::String::format("\x3""l\t000\x4%03d\x0""c", maxWidth); _window->writeString(msg); _window->update(); while (!_vm->shouldQuit()) { Common::KeyCode keyCode = doCursor(msg); + bool refresh = false; if ((keyCode == Common::KEYCODE_BACKSPACE || keyCode == Common::KEYCODE_DELETE) - && line.size() > 0) + && line.size() > 0) { line.deleteLastChar(); - else if (line.size() < maxLen && (line.size() > 0 || keyCode != Common::KEYCODE_SPACE) + refresh = true; + } else if (line.size() < maxLen && (line.size() > 0 || keyCode != Common::KEYCODE_SPACE) && ((isNumeric && keyCode >= Common::KEYCODE_0 && keyCode < Common::KEYCODE_9) || (!isNumeric && keyCode >= Common::KEYCODE_SPACE && keyCode < Common::KEYCODE_DELETE))) { line += (char)keyCode; + refresh = true; } else if (keyCode == Common::KEYCODE_RETURN || keyCode == Common::KEYCODE_KP_ENTER) { break; } else if (keyCode == Common::KEYCODE_ESCAPE) { line = ""; break; } + + if (refresh) { + msg = Common::String::format("\x3""l\t000\x4%03d\x3""c%s", maxWidth, line.c_str()); + _window->writeString(msg); + _window->update(); + } } _vm->_noDirectionSense = false; -- cgit v1.2.3 From 7bbbfd2ad0b310497eacecad7e14230eed6bd80b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 2 Mar 2015 21:39:49 -0500 Subject: XEEN: Implementing more script opcodes --- engines/xeen/debugger.cpp | 5 +- engines/xeen/resources.cpp | 4 + engines/xeen/resources.h | 2 + engines/xeen/screen.cpp | 4 +- engines/xeen/screen.h | 2 +- engines/xeen/scripts.cpp | 182 +++++++++++++++++++++++++++++++++++++++++---- engines/xeen/scripts.h | 6 ++ 7 files changed, 184 insertions(+), 21 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/debugger.cpp b/engines/xeen/debugger.cpp index 35cbaeb58c..d9b4990e97 100644 --- a/engines/xeen/debugger.cpp +++ b/engines/xeen/debugger.cpp @@ -52,7 +52,6 @@ Debugger::Debugger(XeenEngine *vm) : GUI::Debugger(), _vm(vm) { } void Debugger::update() { - Combat &combat = *_vm->_combat; Party &party = *_vm->_party; Spells &spells = *_vm->_spells; @@ -60,7 +59,9 @@ void Debugger::update() { // Cast any specified spell MagicSpell spellId = (MagicSpell)_spellId; _spellId = -1; - spells.castSpell(&party._activeParty[0], spellId); + Character *c = &party._activeParty[0]; + c->_currentSp = 99; + spells.castSpell(c, spellId); } onFrame(); diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 544db24385..0b30ce3e8b 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1585,4 +1585,8 @@ const char *const MONSTER_SPECIAL_ATTACKS[23] = { const char *const IDENTIFY_MONSTERS = "Name\x3""c\t100HP\t140AC\t177#Atks\x3r\t000Special%s%s%s"; +const char *const EVENT_SAMPLES[6] = { + "ahh.voc", "whereto.voc", "gulp.voc", "null.voc", "scream.voc", "laff1.voc" +}; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index e15c509391..6e9ce6ce39 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -562,6 +562,8 @@ extern const char *const MONSTER_SPECIAL_ATTACKS[23]; extern const char *const IDENTIFY_MONSTERS; +extern const char *const EVENT_SAMPLES[6]; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index ac1f0c476b..d9dcbf16f1 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -183,8 +183,8 @@ void Window::fill() { fillRect(_innerBounds, _vm->_screen->_bgColor); } -void Window::writeString(const Common::String &s) { - _vm->_screen->writeString(s, _innerBounds); +Common::String Window::writeString(const Common::String &s) { + return _vm->_screen->writeString(s, _innerBounds); } void Window::drawList(DrawStruct *items, int count) { diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index f8f11a44a4..901e79b5d4 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -92,7 +92,7 @@ public: void fill(); - void writeString(const Common::String &s); + Common::String writeString(const Common::String &s); void drawList(DrawStruct *items, int count); diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index ec00327205..c1743ab7ad 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -102,6 +102,8 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) { _scriptResult = false; _scriptExecuted = false; _var50 = false; + _redrawDone = false; + _windowIndex = -1; } int Scripts::checkEvents() { @@ -132,7 +134,7 @@ int Scripts::checkEvents() { _lineNum = 0; _scriptResult = false; _animCounter = 0; -// int var4E = 0; + _redrawDone = false; _currentPos = party._mazePosition; _charIndex = 1; _v2 = 1; @@ -366,7 +368,7 @@ void Scripts::cmdSignText(Common::Array<byte> ¶ms) { } void Scripts::cmdNPC(Common::Array<byte> ¶ms) { - warning("TODO: cmdNPC"); + error("TODO: cmdNPC"); } /** @@ -800,18 +802,123 @@ void Scripts::cmdWhoWill(Common::Array<byte> ¶ms) { cmdNoAction(params); } -void Scripts::cmdRndDamage(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdMoveWallObj(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdAlterCellFlag(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdAlterHed(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdDisplayStat(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdSeatTextSml(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdPlayEventVoc(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdDisplayBottom(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdIfMapFlag(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdSelRndChar(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdGiveEnchanted(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdItemType(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdRndDamage(Common::Array<byte> ¶ms) { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + + if (!_redrawDone) { + intf.draw3d(true); + _redrawDone = true; + } + + combat.giveCharDamage(_vm->getRandomNumber(1, params[1]), (DamageType)params[0], _charIndex); + cmdNoAction(params); +} + +void Scripts::cmdMoveWallObj(Common::Array<byte> ¶ms) { + Map &map = *_vm->_map; + + map._mobData._wallItems[params[0]]._position = Common::Point(params[1], params[2]); + cmdNoAction(params); +} + +void Scripts::cmdAlterCellFlag(Common::Array<byte> ¶ms) { + Map &map = *_vm->_map; + Common::Point pt(params[0], params[1]); + map.cellFlagLookup(pt); + + if (map._isOutdoors) { + MazeWallLayers &wallData = map.mazeDataCurrent()._wallData[pt.y][pt.x]; + wallData._data = (wallData._data & 0xFFF0) | params[2]; + } else { + pt.x &= 0xF; + pt.y &= 0xF; + MazeCell &cell = map.mazeDataCurrent()._cells[pt.y][pt.x]; + cell._surfaceId = params[2]; + } + + cmdNoAction(params); +} + +void Scripts::cmdAlterHed(Common::Array<byte> ¶ms) { + Map &map = *_vm->_map; + Party &party = *_vm->_party; + + HeadData::HeadEntry &he = map._headData[party._mazePosition.y][party._mazePosition.x]; + he._left = params[0]; + he._right = params[1]; + + cmdNoAction(params); +} + +void Scripts::cmdDisplayStat(Common::Array<byte> ¶ms) { + Party &party = *_vm->_party; + Window &w = _vm->_screen->_windows[12]; + Character &c = party._activeParty[_charIndex - 1]; + + if (!w._enabled) + w.open(); + w.writeString(Common::String::format(_message.c_str(), c._name.c_str())); + w.update(); + + cmdNoAction(params); +} + +void Scripts::cmdSeatTextSml(Common::Array<byte> ¶ms) { + Interface &intf = *_vm->_interface; + + intf._screenText = Common::String::format("\x2\f08\x3""c\t116\v090%s\x3l\fd\x1", + _message); + intf._upDoorText = true; + intf.draw3d(true); + + cmdNoAction(params); +} + +void Scripts::cmdPlayEventVoc(Common::Array<byte> ¶ms) { + SoundManager &sound = *_vm->_sound; + sound.playSample(nullptr, 0); + File f(EVENT_SAMPLES[params[0]]); + sound.playSample(&f, 1); + + cmdNoAction(params); +} + +void Scripts::cmdDisplayBottom(Common::Array<byte> ¶ms) { + _windowIndex = 12; + + display(false, 0); + cmdNoAction(params); +} + +void Scripts::cmdIfMapFlag(Common::Array<byte> ¶ms) { + Map &map = *_vm->_map; + MazeMonster &monster = map._mobData._monsters[params[0]]; + + if (monster._position.x >= 32 || monster._position.y >= 32) { + _lineNum = params[1] - 1; + } + + cmdNoAction(params); +} + +void Scripts::cmdSelRndChar(Common::Array<byte> ¶ms) { + _charIndex = _vm->getRandomNumber(1, _vm->_party->_activeParty.size()); + cmdNoAction(params); +} + +void Scripts::cmdGiveEnchanted(Common::Array<byte> ¶ms) { + if (params[0] < 35) { + + } + error("TODO"); +} + +void Scripts::cmdItemType(Common::Array<byte> ¶ms) { + _itemType = params[0]; + + cmdNoAction(params); +} /** * Disable all the scripts at the party's current position @@ -840,7 +947,13 @@ void Scripts::cmdCheckProtection(Common::Array<byte> ¶ms) { void Scripts::cmdChooseNumeric(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdDisplayLarge(Common::Array<byte> ¶ms) { error("TODO"); } + +void Scripts::cmdDisplayLarge(Common::Array<byte> ¶ms) { + error("TODO: Implement event text loading"); + + display(true, 0); + cmdNoAction(params); +} /** * Exchange the positions of two objects in the maze @@ -868,7 +981,8 @@ void Scripts::cmdFallToMap(Common::Array<byte> ¶ms) { } void Scripts::cmdDisplayMain(Common::Array<byte> ¶ms) { - error("TODO"); + display(false, 0); + cmdNoAction(params); } /** @@ -1333,4 +1447,40 @@ bool Scripts::copyProtectionCheck() { return true; } +void Scripts::display(bool justifyFlag, int var46) { + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Screen &screen = *_vm->_screen; + Window &w = screen._windows[_windowIndex]; + + if (!_redrawDone) { + intf.draw3d(true); + _redrawDone = true; + } + screen._windows[38].close(); + + if (!justifyFlag) + _displayMessage = Common::String::format("\r\x3""c%s", _message.c_str()); + + if (!w._enabled) + w.open(); + + while (!_vm->shouldQuit()) { + _displayMessage = w.writeString(_displayMessage); + w.update(); + if (_displayMessage.empty()) + break; + events.clearEvents(); + + do { + events.updateGameCounter(); + intf.draw3d(true); + + events.wait(1, true); + } while (!_vm->shouldQuit() && !events.isKeyMousePressed()); + + w.writeString(justifyFlag ? "\r" : "\r\x3""c"); + } +} + } // End of namespace Xeen diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 29de5b8b37..15550dd9c0 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -147,9 +147,13 @@ private: int _scriptResult; bool _scriptExecuted; bool _var50; + int _windowIndex; + bool _redrawDone; MazeEvent *_event; Common::Point _currentPos; Common::Stack<StackEntry> _stack; + Common::String _message; + Common::String _displayMessage; void doOpcode(MazeEvent &event); void cmdDisplay1(Common::Array<byte> ¶ms); @@ -219,6 +223,8 @@ private: bool ifProc(int action, uint32 mask, int mode, int charIndex); bool copyProtectionCheck(); + + void display(bool justifyFlag, int var46); public: int _animCounter; bool _eventSkipped; -- cgit v1.2.3 From de5aedcb0c559754697dc534e559820f466afdf2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 2 Mar 2015 23:13:01 -0500 Subject: XEEN: Implemented cmNPC and TownMessage dialog class --- engines/xeen/font.cpp | 4 +- engines/xeen/font.h | 2 +- engines/xeen/screen.cpp | 2 +- engines/xeen/screen.h | 2 +- engines/xeen/scripts.cpp | 6 ++- engines/xeen/town.cpp | 115 +++++++++++++++++++++++++++++++++++++++++++++++ engines/xeen/town.h | 18 ++++++++ 7 files changed, 143 insertions(+), 6 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp index 53308ae248..bfdc4bde6b 100644 --- a/engines/xeen/font.cpp +++ b/engines/xeen/font.cpp @@ -65,7 +65,7 @@ void FontSurface::writeSymbol(int symbolId) { * @remarks Note that bounds is just used for wrapping purposes. Unless * justification is set, the message will be written at _writePos */ -Common::String FontSurface::writeString(const Common::String &s, const Common::Rect &bounds) { +const char *FontSurface::writeString(const Common::String &s, const Common::Rect &bounds) { _displayString = s.c_str(); assert(_fontData); @@ -250,7 +250,7 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R break; } - return Common::String(_displayString); + return _displayString; } /** diff --git a/engines/xeen/font.h b/engines/xeen/font.h index db61e3ea59..caaa03c5ba 100644 --- a/engines/xeen/font.h +++ b/engines/xeen/font.h @@ -63,7 +63,7 @@ public: void writeSymbol(int symbolId); - Common::String writeString(const Common::String &s, const Common::Rect &clipRect); + const char *writeString(const Common::String &s, const Common::Rect &clipRect); }; } // End of namespace Xeen diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index d9dcbf16f1..80f0149d7c 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -183,7 +183,7 @@ void Window::fill() { fillRect(_innerBounds, _vm->_screen->_bgColor); } -Common::String Window::writeString(const Common::String &s) { +const char *Window::writeString(const Common::String &s) { return _vm->_screen->writeString(s, _innerBounds); } diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 901e79b5d4..21b7e8992e 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -92,7 +92,7 @@ public: void fill(); - Common::String writeString(const Common::String &s); + const char *writeString(const Common::String &s); void drawList(DrawStruct *items, int count); diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index c1743ab7ad..53eebb9675 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -368,7 +368,11 @@ void Scripts::cmdSignText(Common::Array<byte> ¶ms) { } void Scripts::cmdNPC(Common::Array<byte> ¶ms) { - error("TODO: cmdNPC"); + Map &map = *_vm->_map; + + if (TownMessage::show(_vm, params[2], _message, map._events._text[params[1]], + params[3])) + _lineNum = params[4]; } /** diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 0934aef34f..a3033b2140 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -1192,4 +1192,119 @@ bool Town::isActive() const { return _townSprites.size() > 0 && !_townSprites[0].empty(); } +/*------------------------------------------------------------------------*/ + +bool TownMessage::show(XeenEngine *vm, int portrait, const Common::String &name, + const Common::String &text, int confirm) { + TownMessage *dlg = new TownMessage(vm); + bool result = dlg->execute(portrait, name, text, confirm); + delete dlg; + + return result; +} + +bool TownMessage::execute(int portrait, const Common::String &name, const Common::String &text, + int confirm) { + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Screen &screen = *_vm->_screen; + Town &town = *_vm->_town; + Window &w = screen._windows[11]; + + town._townMaxId = 4; + town._townActionId = 7; + town._drawFrameIndex = 0; + town._townPos = Common::Point(23, 22); + + if (!confirm) + loadButtons(); + + if (town._townSprites[0].empty()) { + town._townSprites[0].load(Common::String::format("face%02d.fac", portrait)); + town._townSprites[1].load("frame.fac"); + } + + if (!w._enabled) + w.open(); + + int result = -1; + Common::String msgText = text; + for (;;) { + Common::String msg = Common::String::format("\r\v014\x03c\t125%s\t000\v054%s", + name.c_str(), msgText.c_str()); + const char *msgEnd = w.writeString(msg.c_str()); + int wordCount = 0; + + for (const char *msgP = msg.c_str(); msgP < msgEnd; ++msgP) { + if (*msgP == ' ') + ++wordCount; + } + + town._drawCtr2 = wordCount * 2; + town._townSprites[1].draw(screen, 0, Common::Point(16, 16)); + town._townSprites[0].draw(screen, town._drawFrameIndex, Common::Point(23, 22)); + w.update(); + + if (!msgEnd) { + // Doesn't look like the code here in original can ever be reached + assert(0); + } + + if (confirm == 2) { + intf._face1State = intf._face2State = 2; + return false; + } + + do { + events.clearEvents(); + events.updateGameCounter(); + if (msgEnd) + clearButtons(); + + do { + events.wait(3, true); + checkEvents(_vm); + if (_vm->shouldQuit()) + return false; + + town.drawTownAnim(false); + events.updateGameCounter(); + } while (!_buttonValue); + + if (msgEnd) + break; + + if (!msgEnd) { + if (confirm || _buttonValue == Common::KEYCODE_ESCAPE || + _buttonValue == Common::KEYCODE_n) + result = 0; + else if (_buttonValue == Common::KEYCODE_y) + result = 1; + } + } while (result == -1); + + if (msgEnd) { + msgText = Common::String(msgEnd); + town._drawCtr2 = wordCount; + continue; + } + } while (result == -1); + + intf._face1State = intf._face2State = 2; + if (!confirm) + intf.mainIconsPrint(); + + town._townSprites[0].clear(); + town._townSprites[1].clear(); + return result == 1; +} + +void TownMessage::loadButtons() { + _iconSprites.load("confirm.icn"); + + addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_y, &_iconSprites); + addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_n, &_iconSprites); + addButton(Common::Rect(), Common::KEYCODE_ESCAPE); +} + } // End of namespace Xeen diff --git a/engines/xeen/town.h b/engines/xeen/town.h index 8f6ef15710..5aa31e571c 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -32,8 +32,10 @@ namespace Xeen { class XeenEngine; +class TownMessage; class Town: public ButtonContainer { + friend class TownMessage; private: XeenEngine *_vm; SpriteResource _icons1, _icons2; @@ -105,6 +107,22 @@ public: bool isActive() const; }; +class TownMessage : public ButtonContainer { +private: + XeenEngine *_vm; + SpriteResource _iconSprites; + + TownMessage(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + bool execute(int portrait, const Common::String &name, + const Common::String &text, int confirm); + + void loadButtons(); +public: + static bool show(XeenEngine *vm, int portrait, const Common::String &name, + const Common::String &text, int confirm); +}; + } // End of namespace Xeen #endif /* XEEN_SPELLS_H */ -- cgit v1.2.3 From 66dc9ac74645da3aec55edc85c59b73d5724ba43 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 3 Mar 2015 21:26:20 -0500 Subject: XEEN: Implement give/take script opcodes --- engines/xeen/party.cpp | 5 ++ engines/xeen/party.h | 2 + engines/xeen/scripts.cpp | 219 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 222 insertions(+), 4 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 5e111e61b4..9f56b98c4c 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -744,4 +744,9 @@ bool Party::canShoot() const { return false; } +bool Party::giveTake(int mode1, uint32 mask1, int mode2, int mask2, int charIdx) { + error("TODO"); +} + + } // End of namespace Xeen diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 483c3f43ec..445380b893 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -175,6 +175,8 @@ public: bool arePacksFull() const; bool canShoot() const; + + bool giveTake(int mode1, uint32 mask1, int mode2, int mask2, int charIdx); }; } // End of namespace Xeen diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 53eebb9675..7cb487c89d 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -372,7 +372,9 @@ void Scripts::cmdNPC(Common::Array<byte> ¶ms) { if (TownMessage::show(_vm, params[2], _message, map._events._text[params[1]], params[3])) - _lineNum = params[4]; + _lineNum = params[4] - 1; + + cmdNoAction(params); } /** @@ -484,7 +486,7 @@ void Scripts::cmdIf(Common::Array<byte> ¶ms) { } else { result = false; for (int idx = 0; idx < (int)party._activeParty.size() && !result; ++idx) { - if (_charIndex == 0 || (_charIndex == 8 && idx != _v2)) { + if (_charIndex == 0 || (_charIndex == 8 && (int)idx != _v2)) { result = ifProc(params[0], mask, _event->_opcode - 8, idx); } } @@ -511,7 +513,213 @@ void Scripts::cmdMoveObj(Common::Array<byte> ¶ms) { } } -void Scripts::cmdTakeOrGive(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdTakeOrGive(Common::Array<byte> ¶ms) { + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + int mode1, mode2, mode3; + uint32 mask1, mask2, mask3; + byte *extraP; + // TODO: See if this needs to maintain values set in other opcodes + int param2 = 0; + + mode1 = params[0]; + switch (mode1) { + case 16: + case 34: + case 100: + mask1 = (params[4] << 24) | (params[3] << 16) | (params[2] << 8) | params[1]; + extraP = ¶ms[5]; + break; + case 25: + case 35: + case 101: + case 106: + mask1 = (params[2] << 8) | params[1]; + extraP = ¶ms[3]; + break; + default: + mask1 = params[1]; + extraP = ¶ms[2]; + break; + } + + mode2 = *extraP++; + switch (mode2) { + case 16: + case 34: + case 100: + mask2 = (extraP[3] << 24) | (extraP[2] << 16) | (extraP[1] << 8) | extraP[0]; + extraP += 4; + break; + case 25: + case 35: + case 101: + case 106: + mask2 = (extraP[1] << 8) | extraP[0]; + extraP += 2; + break; + default: + mask2 = extraP[0]; + extraP++; + break; + } + + mode3 = *extraP++; + switch (mode3) { + case 16: + case 34: + case 100: + mask3 = (extraP[3] << 24) | (extraP[2] << 16) | (extraP[1] << 8) | extraP[0]; + break; + case 25: + case 35: + case 101: + case 106: + mask3 = (extraP[1] << 8) | extraP[0]; + break; + default: + mask3 = extraP[0]; + break; + } + + if (mode2) + screen.closeWindows(); + + switch (_event->_opcode) { + case OP_TakeOrGive_2: + if (_charIndex == 0 || _charIndex == 8) { + for (uint idx = 0; idx < party._activeParty.size(); ++idx) { + if (_charIndex == 0 || (_charIndex == 8 && (int)idx != _v2)) { + if (ifProc(params[0], mask1, _event->_opcode == OP_TakeOrGive_4 ? 2 : 1, idx)) { + party.giveTake(0, 0, mode2, mask2, idx); + if (mode2 == 82) + break; + } + } + } + } else if (ifProc(params[0], mask1, _event->_opcode == OP_TakeOrGive_4 ? 2 : 1, _charIndex - 1)) { + party.giveTake(0, 0, mode2, mask2, _charIndex - 1); + } + break; + + case OP_TakeOrGive_3: + if (_charIndex == 0 || _charIndex == 8) { + for (uint idx = 0; idx < party._activeParty.size(); ++idx) { + if (_charIndex == 0 || (_charIndex == 8 && (int)idx != _v2)) { + if (ifProc(params[0], mask1, 1, idx) && ifProc(mode2, mask2, 1, idx)) { + party.giveTake(0, 0, mode2, mask3, idx); + if (mode2 == 82) + break; + } + } + } + } else if (ifProc(params[0], mask1, 1, _charIndex - 1) && + ifProc(mode2, mask2, 1, _charIndex - 1)) { + party.giveTake(0, 0, mode2, mask3, _charIndex - 1); + } + break; + + case OP_TakeOrGive_4: + if (_charIndex == 0 || _charIndex == 8) { + for (uint idx = 0; idx < party._activeParty.size(); ++idx) { + if (_charIndex == 0 || (_charIndex == 8 && (int)idx != _v2)) { + if (ifProc(params[0], mask1, _event->_opcode == OP_TakeOrGive_4 ? 2 : 1, idx)) { + party.giveTake(0, 0, mode2, mask2, idx); + if (mode2 == 82) + break; + } + } + } + } else if (ifProc(params[0], mask1, 1, _charIndex - 1)) { + party.giveTake(0, 0, mode2, mask2, _charIndex - 1); + } + break; + + default: + if (_charIndex == 0 || _charIndex == 8) { + for (uint idx = 0; idx < party._activeParty.size(); ++idx) { + if (_charIndex == 0 || (_charIndex == 8 && (int)idx != _v2)) { + party.giveTake(mode1, mask1, mode1, mask2, idx); + + switch (mode1) { + case 8: + mode1 = 0; + // Deliberate fall-through + case 21: + case 66: + if (param2) { + switch (mode2) { + case 82: + mode1 = 0; + // Deliberate fall-through + case 21: + case 34: + case 35: + case 65: + case 66: + case 100: + case 101: + case 106: + if (param2) + continue; + + // Break out of character loop + idx = party._activeParty.size(); + break; + } + } + break; + + case 34: + case 35: + case 65: + case 100: + case 101: + case 106: + if (param2) { + _lineNum = -1; + return; + } + + // Break out of character loop + idx = party._activeParty.size(); + break; + + default: + switch (mode2) { + case 82: + mode1 = 0; + // Deliberate fall-through + case 21: + case 34: + case 35: + case 65: + case 66: + case 100: + case 101: + case 106: + if (param2) + continue; + + // Break out of character loop + idx = party._activeParty.size(); + break; + } + break; + } + } + } + } else { + if (!party.giveTake(mode1, mask1, mode2, mask2, _charIndex - 1)) { + if (mode2 == 79) + screen.closeWindows(); + } + } + break; + } + + cmdNoAction(params); +} /** * Move to the next line of the script @@ -949,7 +1157,10 @@ void Scripts::cmdCheckProtection(Common::Array<byte> ¶ms) { cmdExit(params); } -void Scripts::cmdChooseNumeric(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdChooseNumeric(Common::Array<byte> ¶ms) { + error("TODO"); +} + void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> ¶ms) { error("TODO"); } void Scripts::cmdDisplayLarge(Common::Array<byte> ¶ms) { -- cgit v1.2.3 From 8101f8d03ba755dc9a71d351b10b279276a67999 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 3 Mar 2015 23:20:51 -0500 Subject: XEEN: More script opcodes --- engines/xeen/scripts.cpp | 77 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 7cb487c89d..1474b3ee58 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -1120,10 +1120,67 @@ void Scripts::cmdSelRndChar(Common::Array<byte> ¶ms) { } void Scripts::cmdGiveEnchanted(Common::Array<byte> ¶ms) { - if (params[0] < 35) { + Party &party = *_vm->_party; + bool isDarkCc = _vm->_files->_isDarkCc; + + if (params[0] >= 35) { + if (params[0] < 49) { + for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { + XeenItem &item = party._treasure._armor[idx]; + if (!item.empty()) { + item._id = params[0] - 35; + item._material = params[1]; + item._bonusFlags = params[2]; + party._treasure._hasItems = true; + break; + } + } + + cmdNoAction(params); + return; + } else if (params[0] < 60) { + for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { + XeenItem &item = party._treasure._accessories[idx]; + if (!item.empty()) { + item._id = params[0] - 49; + item._material = params[1]; + item._bonusFlags = params[2]; + party._treasure._hasItems = true; + break; + } + } + + cmdNoAction(params); + return; + } else if (params[0] < 82) { + for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { + XeenItem &item = party._treasure._misc[idx]; + if (!item.empty()) { + item._id = params[0]; + item._material = params[1]; + item._bonusFlags = params[2]; + party._treasure._hasItems = true; + break; + } + } + cmdNoAction(params); + return; + } else { + party._gameFlags[6 + params[0]]++; + } + } + + for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { + XeenItem &item = party._treasure._weapons[idx]; + if (!item.empty()) { + item._id = params[0]; + item._material = params[1]; + item._bonusFlags = params[2]; + party._treasure._hasItems = true; + break; + } } - error("TODO"); } void Scripts::cmdItemType(Common::Array<byte> ¶ms) { @@ -1161,7 +1218,21 @@ void Scripts::cmdChooseNumeric(Common::Array<byte> ¶ms) { error("TODO"); } -void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> ¶ms) { + Interface &intf = *_vm->_interface; + Map &map = *_vm->_map; + Window &w = _vm->_screen->_windows[12]; + + Common::String msg = Common::String::format("\r\x03c\t000\v007%s\n\n%s", + map._events._text[params[1]].c_str()); + w.close(); + w.open(); + w.writeString(msg); + w.update(); + + YesNo::show(_vm, true); + _lineNum = -1; +} void Scripts::cmdDisplayLarge(Common::Array<byte> ¶ms) { error("TODO: Implement event text loading"); -- cgit v1.2.3 From 15d375bc4471788b3323875a54a81a9a754ed034 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 4 Mar 2015 07:45:13 -0500 Subject: XEEN: Implement remaining missing code in checkEvents --- engines/xeen/party.h | 1 + engines/xeen/scripts.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++--- engines/xeen/town.cpp | 4 ++++ engines/xeen/town.h | 2 ++ 4 files changed, 53 insertions(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 445380b893..df6864da33 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -141,6 +141,7 @@ public: DamageType _damageType; bool _dead; Treasure _treasure; + Treasure _savedTreasure; public: Party(XeenEngine *vm); diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 1474b3ee58..1656acd2ee 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -114,6 +114,8 @@ int Scripts::checkEvents() { Party &party = *_vm->_party; Screen &screen = *_vm->_screen; SoundManager &sound = *_vm->_sound; + Town &town = *_vm->_town; + bool isDarkCc = _vm->_files->_isDarkCc; _refreshIcons = false; _itemType = 0; @@ -125,9 +127,15 @@ int Scripts::checkEvents() { //int items = _treasureItems; if (party._treasure._gold & party._treasure._gems) { - // TODO + // Backup any current treasure data + party._savedTreasure = party._treasure; + party._treasure._hasItems = false; + party._treasure._gold = 0; + party._treasure._gems = 0; } else { - // TODO + party._savedTreasure._hasItems = false; + party._savedTreasure._gold = 0; + party._savedTreasure._gems = 0; } do { @@ -176,7 +184,33 @@ int Scripts::checkEvents() { intf.drawParty(true); } - // TODO + party.checkPartyDead(); + if (party._treasure._hasItems || party._treasure._gold || party._treasure._gems) + party.giveTreasure(); + + if (_animCounter > 0 && intf._objNumber) { + MazeObject &selectedObj = map._mobData._objects[intf._objNumber - 1]; + + if (selectedObj._spriteId == (isDarkCc ? 15 : 16)) { + for (uint idx = 0; idx < 16; ++idx) { + MazeObject &obj = map._mobData._objects[idx]; + if (obj._spriteId == (isDarkCc ? 62 : 57)) { + selectedObj._id = idx; + selectedObj._spriteId = isDarkCc ? 62 : 57; + break; + } + } + } else if (selectedObj._spriteId == 73) { + for (uint idx = 0; idx < 16; ++idx) { + MazeObject &obj = map._mobData._objects[idx]; + if (obj._spriteId == 119) { + selectedObj._id = idx; + selectedObj._spriteId = 119; + break; + } + } + } + } _animCounter = 0; _vm->_mode = oldMode; @@ -202,6 +236,15 @@ int Scripts::checkEvents() { w.close(); } + // Restore saved treasure + if (party._savedTreasure._hasItems || party._savedTreasure._gold || + party._savedTreasure._gems) { + party._treasure = party._savedTreasure; + } + + // Clear any town loaded sprites + town.clearSprites(); + _v2 = 1; Common::fill(&intf._charFX[0], &intf._charFX[6], 0); diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index a3033b2140..9b4bfa3ab1 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -1192,6 +1192,10 @@ bool Town::isActive() const { return _townSprites.size() > 0 && !_townSprites[0].empty(); } +void Town::clearSprites() { + _townSprites.clear(); +} + /*------------------------------------------------------------------------*/ bool TownMessage::show(XeenEngine *vm, int portrait, const Common::String &name, diff --git a/engines/xeen/town.h b/engines/xeen/town.h index 5aa31e571c..c64ef891f1 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -105,6 +105,8 @@ public: void drawTownAnim(bool flag); bool isActive() const; + + void clearSprites(); }; class TownMessage : public ButtonContainer { -- cgit v1.2.3 From 652a6623156b6c6bba8ca49e038945fd0c2b7780 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 4 Mar 2015 08:49:05 -0500 Subject: XEEN: Implement cmdChooseNumeric script opcode --- engines/xeen/dialogs_input.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++ engines/xeen/dialogs_input.h | 14 ++++++++ engines/xeen/scripts.cpp | 28 +++++++++++++--- engines/xeen/xeen.h | 1 + 4 files changed, 113 insertions(+), 4 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_input.cpp b/engines/xeen/dialogs_input.cpp index 3626441c7c..8b754ab6de 100644 --- a/engines/xeen/dialogs_input.cpp +++ b/engines/xeen/dialogs_input.cpp @@ -201,5 +201,79 @@ int NumericInput::execute(int maxLength, int maxWidth) { return 0; } +/*------------------------------------------------------------------------*/ + +int Choose123::show(XeenEngine *vm, int numOptions) { + assert(numOptions <= 3); + Choose123 *dlg = new Choose123(vm); + int result = dlg->execute(numOptions); + delete dlg; + + return result; +} + +int Choose123::execute(int numOptions) { + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Screen &screen = *_vm->_screen; + Town &town = *_vm->_town; + + Mode oldMode = _vm->_mode; + _vm->_mode = MODE_DIALOG_123; + + loadButtons(numOptions); + _iconSprites.draw(screen, 7, Common::Point(232, 74)); + drawButtons(&screen); + screen._windows[34].update(); + + int result = -1; + while (result == -1) { + do { + events.updateGameCounter(); + int delay; + if (town.isActive()) { + town.drawTownAnim(true); + delay = 3; + } else { + intf.draw3d(true); + delay = 1; + } + + events.wait(delay, true); + if (_vm->shouldQuit()) + return 0; + } while (!_buttonValue); + + switch (_buttonValue) { + case Common::KEYCODE_ESCAPE: + result = 0; + break; + case Common::KEYCODE_1: + case Common::KEYCODE_2: + case Common::KEYCODE_3: { + int v = _buttonValue - Common::KEYCODE_1 + 1; + if (v <= numOptions) + result = v; + break; + } + default: + break; + } + } + + _vm->_mode = oldMode; + intf.mainIconsPrint(); +} + +void Choose123::loadButtons(int numOptions) { + _iconSprites.load("choose.icn"); + + if (numOptions >= 1) + addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_1, &_iconSprites); + if (numOptions >= 2) + addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_2, &_iconSprites); + if (numOptions >= 3) + addButton(Common::Rect(286, 75, 311, 95), Common::KEYCODE_3, &_iconSprites); +} } // End of namespace Xeen diff --git a/engines/xeen/dialogs_input.h b/engines/xeen/dialogs_input.h index 30e4cb2854..2f30b73973 100644 --- a/engines/xeen/dialogs_input.h +++ b/engines/xeen/dialogs_input.h @@ -64,6 +64,20 @@ public: static int show(XeenEngine *vm, int window, int maxLength, int maxWidth); }; +class Choose123 : public ButtonContainer { +private: + XeenEngine *_vm; + SpriteResource _iconSprites; + + Choose123(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + int execute(int numOptions); + + void loadButtons(int numOptions); +public: + static int show(XeenEngine *vm, int numOptions); +}; + } // End of namespace Xeen #endif /* XEEN_DIALOGS_STRING_INPUT_H */ diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 1656acd2ee..790e3d729e 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -954,7 +954,20 @@ void Scripts::cmdConfirmWord(Common::Array<byte> ¶ms) { cmdNoAction(params); } -void Scripts::cmdDamage(Common::Array<byte> ¶ms) { error("TODO"); } +void Scripts::cmdDamage(Common::Array<byte> ¶ms) { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + + if (!_redrawDone) { + intf.draw3d(true); + _redrawDone = true; + } + + int damage = (params[1] << 8) | params[0]; + combat.giveCharDamage(damage, (DamageType)params[2], _charIndex); + + cmdNoAction(params); +} /** * Jump if a random number matches a given value @@ -1164,7 +1177,6 @@ void Scripts::cmdSelRndChar(Common::Array<byte> ¶ms) { void Scripts::cmdGiveEnchanted(Common::Array<byte> ¶ms) { Party &party = *_vm->_party; - bool isDarkCc = _vm->_files->_isDarkCc; if (params[0] >= 35) { if (params[0] < 49) { @@ -1257,12 +1269,20 @@ void Scripts::cmdCheckProtection(Common::Array<byte> ¶ms) { cmdExit(params); } +/** + * Given a number of options, and a list of line numbers associated with + * those options, jumps to whichever line for the option the user selects + */ void Scripts::cmdChooseNumeric(Common::Array<byte> ¶ms) { - error("TODO"); + int choice = Choose123::show(_vm, params[0]); + if (choice) { + _lineNum = params[choice] - 1; + } + + cmdNoAction(params); } void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> ¶ms) { - Interface &intf = *_vm->_interface; Map &map = *_vm->_map; Window &w = _vm->_screen->_windows[12]; diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 71859413aa..4180a17650 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -88,6 +88,7 @@ enum Mode { MODE_9 = 9, MODE_CHARACTER_INFO = 10, MODE_12 = 12, + MODE_DIALOG_123 = 13, MODE_17 = 17, MODE_86 = 86 }; -- cgit v1.2.3 From 76ba9185dd6e26451e3cd8e0dacce8a539156b1c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 18 Oct 2015 12:36:56 -0400 Subject: XEEN: Change sprite drawing to use the same algorithm as original --- engines/xeen/sprites.cpp | 255 ++++++++++++++++++++++------------------------- engines/xeen/sprites.h | 16 ++- 2 files changed, 132 insertions(+), 139 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index b596432992..8ae7e41b95 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -117,6 +117,17 @@ void SpriteResource::clear() { */ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &pt, const Common::Rect &bounds, int flags, int scale) { + static const uint SCALE_TABLE[] = { + 0xFFFF, 0xFFEF, 0xEFEF, 0xEFEE, 0xEEEE, 0xEEAE, 0xAEAE, 0xAEAA, + 0xAAAA, 0xAA8A, 0x8A8A, 0x8A88, 0x8888, 0x8880, 0x8080, 0x8000 + }; + static const int PATTERN_STEPS[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 }; + + uint16 scaleMask = SCALE_TABLE[scale]; + uint16 scaleMaskX = scaleMask, scaleMaskY = scaleMask; + bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0; + int xInc = flipped ? -1 : 1; + // Get cell header Common::MemoryReadStream f(_data, _filesize); f.seek(offset); @@ -125,62 +136,65 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi int yOffset = f.readUint16LE(); int height = f.readUint16LE(); - // TODO: I don't currently know the algorithm the original used for scaling. - // This is a best fit estimate that every increment of the scale field - // reduces the size of a sprite by approximately 6.6% - int newScale = MAX(100.0 - 6.6 * scale, 0.0); - if (newScale == 0) - return; - setupScaling(newScale, xOffset + width, yOffset + height); - - Common::Point destPos = pt; - destPos.x += (xOffset + width - _scaledWidth) / 2; - - bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0; - int xInc = flipped ? -1 : 1; - + // Figure out drawing x, y + Common::Point destPos; + destPos.x = pt.x + getScaledVal(xOffset, scaleMaskX); + destPos.x += (width - getScaledVal(width, scaleMaskX)) / 2; + + destPos.y = pt.y + getScaledVal(yOffset, scaleMaskY); + + // If the flags allow the dest surface to be resized, ensure dest surface is big enough if (flags & SPRFLAG_RESIZE) { if (dest.w < (xOffset + width) || dest.h < (yOffset + height)) dest.create(xOffset + width, yOffset + height); } - // The pattern steps used in the pattern command - const int patternSteps[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 }; + + uint16 scaleMaskXCopy = scaleMaskX; + Common::Rect drawBounds; + drawBounds.left = SCREEN_WIDTH; + drawBounds.top = SCREEN_HEIGHT; + drawBounds.right = drawBounds.bottom = 0; // Main loop - int opr1, opr2; - int32 pos; - int yIndex = yOffset; - int yPos = destPos.y + getScaledValue(yOffset); - for (int yCtr = 0, byteCount = 0; yCtr < height; ++yCtr, ++yIndex, byteCount = 0) { + for (int yCtr = height; yCtr > 0; --yCtr) { // The number of bytes in this scan line int lineLength = f.readByte(); if (lineLength == 0) { // Skip the specified number of scan lines int numLines = f.readByte(); - for (int idx = 0; idx < numLines; ++idx, ++yIndex, ++yCtr) { - if (_lineDist[yIndex]) - ++yPos; - } - } else if (destPos.y < bounds.top || yPos >= bounds.bottom - || !_lineDist[yIndex]) { + destPos.y += getScaledVal(numLines, scaleMaskY); + yCtr -= numLines; + continue; + } + + // Roll the scale mask + uint bit = (scaleMaskY >> 15) & 1; + scaleMaskY = ((scaleMaskY & 0x7fff) << 1) + bit; + + if (!bit) { + // Not a line to be drawn due to scaling down + f.skip(lineLength); + } else if (destPos.y < bounds.top || destPos.y >= bounds.bottom) { // Skip over the bytes of the line f.skip(lineLength); + destPos.y++; } else { - const byte *lineStartP = (const byte *)dest.getBasePtr(bounds.left, yPos); - const byte *lineEndP = (const byte *)dest.getBasePtr(bounds.right, yPos); - - // Skip the transparent pixels at the beginning of the scan line - int xPos = f.readByte() + xOffset; ++byteCount; - int xAmt = getScaledValue(flipped ? xOffset + width - xPos : xPos); - int xIndex = 0; - - byte *destP = (byte *)dest.getBasePtr(destPos.x + xAmt, yPos); - ++yPos; - - while (byteCount < lineLength) { - // The next byte is an opcode that determines what - // operators are to follow and how to interpret them. + scaleMaskX = scaleMaskXCopy; + int xOffset = f.readByte(); + + // Initialize the array to hold the temporary data for the line. We do this to make it simpler + // to handle both deciding which pixels to draw in a scaled image, as well as when images + // have been horizontally flipped + int tempLine[SCREEN_WIDTH]; + Common::fill(&tempLine[0], &tempLine[SCREEN_WIDTH], -1); + int *lineP = flipped ? &tempLine[width - 1 - xOffset] : &tempLine[xOffset]; + + // Build up the line + int byteCount, opr1, opr2; + int32 pos; + for (byteCount = 1; byteCount < lineLength; ) { + // The next byte is an opcode that determines what operators are to follow and how to interpret them. int opcode = f.readByte(); ++byteCount; // Decode the opcode @@ -190,26 +204,18 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi switch (cmd) { case 0: // The following len + 1 bytes are stored as indexes into the color table. case 1: // The following len + 33 bytes are stored as indexes into the color table. - for (int i = 0; i < opcode + 1; ++i, ++xPos) { + for (int i = 0; i < opcode + 1; ++i, ++byteCount) { byte b = f.readByte(); - ++byteCount; - - if (_lineDist[xIndex++]) { - if (destP >= lineStartP && destP < lineEndP) - *destP = b; - destP += xInc; - } + *lineP = b; + lineP += xInc; } break; case 2: // The following byte is an index into the color table, draw it len + 3 times. opr1 = f.readByte(); ++byteCount; - for (int i = 0; i < len + 3; ++i, ++xPos) { - if (_lineDist[xIndex++]) { - if (destP >= lineStartP && destP < lineEndP) - *destP = opr1; - destP += xInc; - } + for (int i = 0; i < len + 3; ++i) { + *lineP = opr1; + lineP += xInc; } break; @@ -218,13 +224,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi pos = f.pos(); f.seek(-opr1, SEEK_CUR); - for (int i = 0; i < len + 4; ++i, ++xPos) { - byte b = f.readByte(); - if (_lineDist[xIndex++]) { - if (destP >= lineStartP && destP < lineEndP) - *destP = b; - destP += xInc; - } + for (int i = 0; i < len + 4; ++i) { + *lineP = f.readByte(); + lineP += xInc; } f.seek(pos, SEEK_SET); @@ -233,31 +235,16 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi case 4: // The following two bytes are indexes into the color table, draw the pair len + 2 times. opr1 = f.readByte(); ++byteCount; opr2 = f.readByte(); ++byteCount; - for (int i = 0; i < len + 2; ++i, xPos += 2) { - if (destP < lineStartP || destP >= (lineEndP - 1)) { - if (_lineDist[xIndex++]) - destP += xInc; - if (_lineDist[xIndex++]) - destP += xInc; - } else { - if (_lineDist[xIndex++]) { - *destP = opr1; - destP += xInc; - } - if (_lineDist[xIndex++]) { - *destP = opr2; - destP += xInc; - } - } + for (int i = 0; i < len + 2; ++i) { + *lineP = opr1; + lineP += xInc; + *lineP = opr2; + lineP += xInc; } break; - case 5: // Skip len + 1 pixels filling them with the transparent color. - for (int idx = 0; idx < (len + 1); ++idx) { - if (_lineDist[xIndex++]) - destP += xInc; - ++xPos; - } + case 5: // Skip len + 1 pixels + lineP += len + 1; break; case 6: // Pattern command. @@ -267,30 +254,54 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi cmd = (opcode >> 2) & 0x0E; opr1 = f.readByte(); ++byteCount; - for (int i = 0; i < len + 3; ++i, ++xPos) { - if (_lineDist[xIndex++]) { - if (destP >= lineStartP && destP < lineEndP) - *destP = opr1; - destP += xInc; - } - opr1 += patternSteps[cmd + (i % 2)]; + for (int i = 0; i < len + 3; ++i) { + *lineP = opr1; + lineP += xInc; + opr1 += PATTERN_STEPS[cmd + (i % 2)]; } break; + default: break; } } - assert(byteCount == lineLength); + + drawBounds.top = MIN(drawBounds.top, destPos.y); + drawBounds.bottom = MAX(drawBounds.bottom, destPos.y); + + // Handle drawing out the line + byte *destP = (byte *)dest.getBasePtr(destPos.x, destPos.y); + int16 xp = destPos.x; + lineP = &tempLine[0]; + + for (int xCtr = 0; xCtr < width; ++xCtr, ++lineP) { + bit = (scaleMaskX >> 15) & 1; + scaleMaskX = ((scaleMaskX & 0x7fff) << 1) + bit; + + if (bit) { + if (*lineP != -1 && xp >= bounds.left && xp < bounds.right) { + *destP = (byte)*lineP; + drawBounds.left = MIN(drawBounds.left, xp); + drawBounds.right = MAX(drawBounds.right, xp); + } + + ++destP; + ++xp; + } + } + + ++destPos.y; } } - - Common::Rect r(Common::Rect( - destPos.x + getScaledValue(xOffset), destPos.y + getScaledValue(yOffset), - destPos.x + getScaledValue(xOffset + width), destPos.y + getScaledValue(yOffset + height))); - r.clip(Common::Rect(0, 0, dest.w, dest.h)); - if (!r.isEmpty()) - dest.addDirtyRect(r); + dest.addDirtyRect(Common::Rect(0, 0, dest.w, dest.h)); + /* + if (drawBounds.isValidRect()) { + drawBounds.clip(Common::Rect(0, 0, dest.w, dest.h)); + if (!drawBounds.isEmpty()) + dest.addDirtyRect(drawBounds); + } + */ } void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, @@ -303,9 +314,6 @@ void SpriteResource::draw(Window &dest, int frame, const Common::Point &destPos, draw(dest, frame, destPos, dest.getBounds(), flags, scale); } -/** - * Draw the sprite onto the given surface - */ void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, const Common::Rect &bounds, int flags, int scale) { // TODO: TO test when I find sprites using scale values and flags @@ -318,47 +326,22 @@ void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPo drawOffset(dest, _index[frame]._offset2, destPos, bounds, flags, scale); } -/** - * Draw the sprite onto the given surface - */ void SpriteResource::draw(XSurface &dest, int frame) { draw(dest, frame, Common::Point()); } -void SpriteResource::setupScaling(int scale, int frameWidth, int frameHeight) { - int highestDim = MAX(frameWidth, frameHeight); - int distCtr = 0; - int distIndex = 0; - _scaledWidth = _scaledHeight = 0; - - do { - distCtr += scale; - if (distCtr < 100) { - _lineDist[distIndex] = false; - } else { - _lineDist[distIndex] = true; - distCtr -= 100; - - if (distIndex < frameWidth) - ++_scaledWidth; - - if (distIndex < frameHeight) - ++_scaledHeight; - } - } while (++distIndex < highestDim); -} +uint SpriteResource::getScaledVal(int xy, uint16 &scaleMask) { + if (!xy) + return 0; -/** - * Returns a scaled value based on a passed in x or y distance - */ -int SpriteResource::getScaledValue(int xy) { - int newVal = 0; + uint result = 0; for (int idx = 0; idx < xy; ++idx) { - if (_lineDist[idx]) - ++newVal; + uint bit = (scaleMask >> 15) & 1; + scaleMask = ((scaleMask & 0x7fff) << 1) + bit; + result += bit; } - - return newVal; + + return result; } } // End of namespace Xeen diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index 0e3a3c3059..ce7b7861b2 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -50,15 +50,22 @@ private: void load(Common::SeekableReadStream &f); + /** + * Draw the sprite onto the given surface + */ void draw(XSurface &dest, int frame, const Common::Point &destPos, const Common::Rect &bounds, int flags = 0, int scale = 0); + /** + * Draw a sprite frame based on a passed offset into the data stream + */ void drawOffset(XSurface &dest, uint16 offset, const Common::Point &pt, const Common::Rect &bounds, int flags, int scale); - void setupScaling(int scale, int frameWidth, int frameHeight); - - int getScaledValue(int xy); + /** + * Scale a co-ordinate value based on the passed scaling mask + */ + static uint getScaledVal(int xy, uint16 &scaleMask); public: SpriteResource(); SpriteResource(const Common::String &filename); @@ -79,6 +86,9 @@ public: void draw(Window &dest, int frame, const Common::Point &destPos, int flags = 0, int scale = 0); + /** + * Draw the sprite onto the given surface + */ void draw(XSurface &dest, int frame); int size() const { return _index.size(); } -- cgit v1.2.3 From 80fcbaf4410c6486986420ba4565c1c3361a1f74 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 18 Oct 2015 12:55:16 -0400 Subject: XEEN: Restore dirty rect handling in sprite drawing --- engines/xeen/sprites.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 8ae7e41b95..218e712433 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -294,14 +294,12 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi ++destPos.y; } } - dest.addDirtyRect(Common::Rect(0, 0, dest.w, dest.h)); - /* + if (drawBounds.isValidRect()) { drawBounds.clip(Common::Rect(0, 0, dest.w, dest.h)); if (!drawBounds.isEmpty()) dest.addDirtyRect(drawBounds); } - */ } void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, -- cgit v1.2.3 From c2c00894f22ed8cf0b3d5fa469d8554ab0df96ef Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 18 Oct 2015 21:35:35 -0400 Subject: XEEN: Implement SPRFLAG_SCENE_CLIPPED drawing flag --- engines/xeen/interface_map.cpp | 74 +++++++++++++++++++++--------------------- engines/xeen/sprites.cpp | 7 ++-- engines/xeen/sprites.h | 2 +- 3 files changed, 43 insertions(+), 40 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index a9e71d4e9c..a08ce808d8 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -60,11 +60,11 @@ OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]), _data[25] = DrawStruct(0, 8, 109); _data[26] = DrawStruct(0, 201, 109); _data[27] = DrawStruct(0, 8, 109); - _data[28] = DrawStruct(1, -64, 61, 14, SPRFLAG_2000); + _data[28] = DrawStruct(1, -64, 61, 14, SPRFLAG_SCENE_CLIPPED); _data[29] = DrawStruct(1, -40, 61, 14, 0); _data[30] = DrawStruct(1, -16, 61, 14, 0); _data[31] = DrawStruct(1, 8, 61, 14, 0); - _data[32] = DrawStruct(1, 128, 61, 14, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000); + _data[32] = DrawStruct(1, 128, 61, 14, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_SCENE_CLIPPED); _data[33] = DrawStruct(1, 104, 61, 14, SPRFLAG_HORIZ_FLIPPED); _data[34] = DrawStruct(1, 80, 61, 14, SPRFLAG_HORIZ_FLIPPED); _data[35] = DrawStruct(1, 56, 61, 14, SPRFLAG_HORIZ_FLIPPED); @@ -120,10 +120,10 @@ OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]), _data[85] = DrawStruct(2, 146, 40, 0, SPRFLAG_HORIZ_FLIPPED); _data[86] = DrawStruct(1, 32, 40, 6, 0); _data[87] = DrawStruct(0, -7, 30, 7, 0); - _data[88] = DrawStruct(0, -112, 30, 7, SPRFLAG_2000); - _data[89] = DrawStruct(0, 98, 30, 7, SPRFLAG_2000); - _data[90] = DrawStruct(0, -112, 30, 8, SPRFLAG_2000); - _data[91] = DrawStruct(0, 98, 30, 8, SPRFLAG_2000); + _data[88] = DrawStruct(0, -112, 30, 7, SPRFLAG_SCENE_CLIPPED); + _data[89] = DrawStruct(0, 98, 30, 7, SPRFLAG_SCENE_CLIPPED); + _data[90] = DrawStruct(0, -112, 30, 8, SPRFLAG_SCENE_CLIPPED); + _data[91] = DrawStruct(0, 98, 30, 8, SPRFLAG_SCENE_CLIPPED); _data[92] = DrawStruct(0, -38, 30, 8, 0); _data[93] = DrawStruct(0, 25, 30, 8, 0); _data[94] = DrawStruct(0, -7, 30, 8, 0); @@ -138,22 +138,22 @@ OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]), _data[103] = DrawStruct(0, 8, 24); _data[104] = DrawStruct(0, 169, 24, 0, SPRFLAG_HORIZ_FLIPPED); _data[105] = DrawStruct(1, 32, 24); - _data[106] = DrawStruct(0, -23, 40, 0, SPRFLAG_2000); - _data[107] = DrawStruct(0, 200, 40, 0, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000); + _data[106] = DrawStruct(0, -23, 40, 0, SPRFLAG_SCENE_CLIPPED); + _data[107] = DrawStruct(0, 200, 40, 0, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_SCENE_CLIPPED); _data[108] = DrawStruct(0, 8, 47); _data[109] = DrawStruct(0, 169, 47, 0, SPRFLAG_HORIZ_FLIPPED); - _data[110] = DrawStruct(1, -56, -4, 0x8000, SPRFLAG_4000 | SPRFLAG_2000); - _data[111] = DrawStruct(0, -5, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); - _data[112] = DrawStruct(0, -67, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[110] = DrawStruct(1, -56, -4, 0x8000, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED); + _data[111] = DrawStruct(0, -5, 2, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED); + _data[112] = DrawStruct(0, -67, 2, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED); _data[113] = DrawStruct(0, 44, 73); _data[114] = DrawStruct(0, 44, 73); - _data[115] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[115] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED); _data[116] = DrawStruct(0, 169, 73); _data[117] = DrawStruct(0, 169, 73); - _data[118] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[118] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED); _data[119] = DrawStruct(0, 110, 73); _data[120] = DrawStruct(0, 110, 73); - _data[121] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[121] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED); _data[122] = DrawStruct(0, 110, 73); _data[123] = DrawStruct(0, 110, 73); _data[124] = DrawStruct(0, 72, 43); @@ -280,16 +280,16 @@ IndoorDrawList::IndoorDrawList() : _data[84] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED); _data[85] = DrawStruct(0, 80, 57, 12, 0); _data[86] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED); - _data[87] = DrawStruct(7, -24, 52, 0, SPRFLAG_2000); + _data[87] = DrawStruct(7, -24, 52, 0, SPRFLAG_SCENE_CLIPPED); _data[88] = DrawStruct(7, 32, 52); _data[89] = DrawStruct(7, 88, 52); _data[90] = DrawStruct(0, 144, 52); - _data[91] = DrawStruct(0, 200, 52, 0, SPRFLAG_2000); - _data[92] = DrawStruct(0, -79, 52, 11, SPRFLAG_2000); + _data[91] = DrawStruct(0, 200, 52, 0, SPRFLAG_SCENE_CLIPPED); + _data[92] = DrawStruct(0, -79, 52, 11, SPRFLAG_SCENE_CLIPPED); _data[93] = DrawStruct(0, -27, 52, 11, 0); _data[94] = DrawStruct(0, 32, 52, 11, 0); _data[95] = DrawStruct(0, 89, 52, 11, 0); - _data[96] = DrawStruct(0, 145, 52, 11, SPRFLAG_2000); + _data[96] = DrawStruct(0, 145, 52, 11, SPRFLAG_SCENE_CLIPPED); _data[97] = DrawStruct(0, -8, 50, 12, 0); _data[98] = DrawStruct(0, -65, 50, 12, 0); _data[99] = DrawStruct(0, 49, 50, 12, 0); @@ -312,17 +312,17 @@ IndoorDrawList::IndoorDrawList() : _data[116] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED); _data[117] = DrawStruct(0, 94, 52, 8, 0); _data[118] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED); - _data[119] = DrawStruct(6, -40, 40, 0, SPRFLAG_2000); + _data[119] = DrawStruct(6, -40, 40, 0, SPRFLAG_SCENE_CLIPPED); _data[120] = DrawStruct(6, 64, 40); - _data[121] = DrawStruct(0, 168, 40, 0, SPRFLAG_2000); - _data[122] = DrawStruct(0, -72, 40, 6, SPRFLAG_2000); + _data[121] = DrawStruct(0, 168, 40, 0, SPRFLAG_SCENE_CLIPPED); + _data[122] = DrawStruct(0, -72, 40, 6, SPRFLAG_SCENE_CLIPPED); _data[123] = DrawStruct(0, 32, 40, 6, 0); - _data[124] = DrawStruct(0, 137, 40, 6, SPRFLAG_2000); + _data[124] = DrawStruct(0, 137, 40, 6, SPRFLAG_SCENE_CLIPPED); _data[125] = DrawStruct(0, -7, 25, 7, 0); - _data[126] = DrawStruct(0, -112, 25, 7, SPRFLAG_2000); - _data[127] = DrawStruct(0, 98, 25, 7, SPRFLAG_2000); - _data[128] = DrawStruct(0, -112, 29, 8, SPRFLAG_2000); - _data[129] = DrawStruct(0, 98, 29, 8, SPRFLAG_2000); + _data[126] = DrawStruct(0, -112, 25, 7, SPRFLAG_SCENE_CLIPPED); + _data[127] = DrawStruct(0, 98, 25, 7, SPRFLAG_SCENE_CLIPPED); + _data[128] = DrawStruct(0, -112, 29, 8, SPRFLAG_SCENE_CLIPPED); + _data[129] = DrawStruct(0, 98, 29, 8, SPRFLAG_SCENE_CLIPPED); _data[130] = DrawStruct(0, -38, 29, 8, 0); _data[131] = DrawStruct(0, 25, 29, 8, 0); _data[132] = DrawStruct(0, -7, 29, 8, 0); @@ -336,23 +336,23 @@ IndoorDrawList::IndoorDrawList() : _data[140] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED); _data[141] = DrawStruct(0, 106, 47, 4, 0); _data[142] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED); - _data[143] = DrawStruct(0, -136, 24, 0, SPRFLAG_2000); + _data[143] = DrawStruct(0, -136, 24, 0, SPRFLAG_SCENE_CLIPPED); _data[144] = DrawStruct(0, 8, 12); _data[145] = DrawStruct(0, 32, 24); _data[146] = DrawStruct(0, 200, 12, 0, SPRFLAG_HORIZ_FLIPPED); - _data[147] = DrawStruct(0, 200, 24, 0, SPRFLAG_2000); + _data[147] = DrawStruct(0, 200, 24, 0, SPRFLAG_SCENE_CLIPPED); _data[148] = DrawStruct(0, 32, 24); - _data[149] = DrawStruct(0, -5, 2, 0, SPRFLAG_4000 | SPRFLAG_2000); - _data[150] = DrawStruct(0, -67, 10, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[149] = DrawStruct(0, -5, 2, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED); + _data[150] = DrawStruct(0, -67, 10, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED); _data[151] = DrawStruct(0, 44, 73); _data[152] = DrawStruct(0, 44, 73); - _data[153] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[153] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED); _data[154] = DrawStruct(0, 169, 73); _data[155] = DrawStruct(0, 169, 73); - _data[156] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[156] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED); _data[157] = DrawStruct(0, 110, 73); _data[158] = DrawStruct(0, 110, 73); - _data[159] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000); + _data[159] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED); _data[160] = DrawStruct(0, 110, 73); _data[161] = DrawStruct(0, 110, 73); _data[162] = DrawStruct(0, 72, 43); @@ -478,7 +478,7 @@ void InterfaceMap::drawMap() { ds2._y = 73; } - ds2._flags = SPRFLAG_4000 | SPRFLAG_2000; + ds2._flags = SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED; ds2._sprites = &_charPowSprites; } @@ -489,7 +489,7 @@ void InterfaceMap::drawMap() { if (ds1._scale == 0x8000) ds1._x /= 3; - ds1._flags = SPRFLAG_4000 | SPRFLAG_2000; + ds1._flags = SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED; ds1._sprites = &_charPowSprites; } } @@ -612,7 +612,7 @@ void InterfaceMap::drawMap() { ds1._y = 73; } - ds1._flags = SPRFLAG_4000 | SPRFLAG_2000; + ds1._flags = SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED; ds1._sprites = &_charPowSprites; } @@ -622,7 +622,7 @@ void InterfaceMap::drawMap() { ds2._scale = combat._elemScale[idx]; if (ds2._scale == 0x8000) ds2._x /= 3; - ds2._flags = SPRFLAG_4000 | SPRFLAG_2000; + ds2._flags = SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED; ds2._sprites = &_charPowSprites; } } diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 218e712433..288d304523 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -30,6 +30,9 @@ namespace Xeen { +#define SCENE_CLIP_LEFT 8 +#define SCENE_CLIP_RIGHT 223 + SpriteResource::SpriteResource() { _filesize = 0; _data = nullptr; @@ -280,7 +283,8 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi scaleMaskX = ((scaleMaskX & 0x7fff) << 1) + bit; if (bit) { - if (*lineP != -1 && xp >= bounds.left && xp < bounds.right) { + if (*lineP != -1 && xp >= bounds.left && xp < bounds.right && + (!(flags & SPRFLAG_SCENE_CLIPPED) || (xp >= SCENE_CLIP_LEFT && xp < SCENE_CLIP_RIGHT))) { *destP = (byte)*lineP; drawBounds.left = MIN(drawBounds.left, xp); drawBounds.right = MAX(drawBounds.right, xp); @@ -317,7 +321,6 @@ void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPo // TODO: TO test when I find sprites using scale values and flags assert(scale != 0x8000); assert(scale >= 0); -// assert((flags & SPRFLAG_2000) == 0); drawOffset(dest, _index[frame]._offset1, destPos, bounds, flags, scale); if (_index[frame]._offset2) diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index ce7b7861b2..2a00ecaf76 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -34,7 +34,7 @@ namespace Xeen { class XeenEngine; class Window; -enum SpriteFlags { SPRFLAG_2000 = 0x2000, SPRFLAG_4000 = 0x4000, +enum SpriteFlags { SPRFLAG_SCENE_CLIPPED = 0x2000, SPRFLAG_4000 = 0x4000, SPRFLAG_HORIZ_FLIPPED = 0x8000, SPRFLAG_RESIZE = 0x10000 }; class SpriteResource { -- cgit v1.2.3 From 0bb223cd3a4840f3da7c3faac701e7814e1ebf82 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 19 Oct 2015 08:55:13 -0400 Subject: XEEN: Fix graphic corruption on images with skipped pixels --- engines/xeen/sprites.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 288d304523..1e7a48eb6f 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -247,7 +247,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi break; case 5: // Skip len + 1 pixels - lineP += len + 1; + lineP += (len + 1) * xInc; break; case 6: // Pattern command. -- cgit v1.2.3 From 43e16714df3688113d8d12533dc780a1d6f872d9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 20 Oct 2015 07:33:30 -0400 Subject: XEEN: Implement sprite enlargement drawing --- engines/xeen/sprites.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 1e7a48eb6f..3491f6fc7b 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -126,10 +126,11 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi }; static const int PATTERN_STEPS[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 }; - uint16 scaleMask = SCALE_TABLE[scale]; + uint16 scaleMask = SCALE_TABLE[scale & 0x7fff]; uint16 scaleMaskX = scaleMask, scaleMaskY = scaleMask; bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0; int xInc = flipped ? -1 : 1; + bool enlarge = (scale & 0x8000) != 0; // Get cell header Common::MemoryReadStream f(_data, _filesize); @@ -283,11 +284,15 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi scaleMaskX = ((scaleMaskX & 0x7fff) << 1) + bit; if (bit) { + // Check whether there's a pixel to write, and we're within the allowable bounds. Note that for + // the SPRFLAG_SCENE_CLIPPED or when scale == 0x8000, we also have an extra horizontal bounds check if (*lineP != -1 && xp >= bounds.left && xp < bounds.right && - (!(flags & SPRFLAG_SCENE_CLIPPED) || (xp >= SCENE_CLIP_LEFT && xp < SCENE_CLIP_RIGHT))) { - *destP = (byte)*lineP; + ((!(flags & SPRFLAG_SCENE_CLIPPED) && !enlarge) || (xp >= SCENE_CLIP_LEFT && xp < SCENE_CLIP_RIGHT))) { drawBounds.left = MIN(drawBounds.left, xp); drawBounds.right = MAX(drawBounds.right, xp); + *destP = (byte)*lineP; + if (enlarge) + *(destP + SCREEN_WIDTH) = (byte)*lineP; } ++destP; @@ -296,6 +301,8 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi } ++destPos.y; + if (enlarge) + ++destPos.y; } } @@ -318,9 +325,6 @@ void SpriteResource::draw(Window &dest, int frame, const Common::Point &destPos, void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, const Common::Rect &bounds, int flags, int scale) { - // TODO: TO test when I find sprites using scale values and flags - assert(scale != 0x8000); - assert(scale >= 0); drawOffset(dest, _index[frame]._offset1, destPos, bounds, flags, scale); if (_index[frame]._offset2) -- cgit v1.2.3 From e06c879a477b4e187a31859e2519767f7e992bdb Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 23 Oct 2015 08:40:56 -0400 Subject: XEEN: Fix displaying sky when outdoors --- engines/xeen/map.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/xeen') diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 021c417528..ff7938746e 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1114,6 +1114,7 @@ void Map::load(int mapId) { _groundSprites.load("water.out"); _tileSprites.load("outdoor.til"); + outdoorList._sky1._sprites = &_skySprites[0]; outdoorList._sky2._sprites = &_skySprites[0]; outdoorList._groundSprite._sprites = &_groundSprites; -- cgit v1.2.3 From 569f3c65b724a1c7be7a64bbfc61ec8aef060033 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Oct 2015 16:14:15 -0400 Subject: XEEN: Beginnings of work on copy protection check method --- engines/xeen/scripts.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 790e3d729e..175292fa1d 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -20,6 +20,7 @@ * */ +#include "common/config-manager.h" #include "xeen/scripts.h" #include "xeen/dialogs_input.h" #include "xeen/dialogs_whowill.h" @@ -1792,7 +1793,11 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { } bool Scripts::copyProtectionCheck() { - // Currentl not implemented + // Only bother doing the protection check if it's been explicitly turned on + if (!ConfMan.getBool("copy_protection")) + return true; + + // Currently not implemented return true; } -- cgit v1.2.3 From 619a165f359251ed82dcd84d2c0ab221671af1d7 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 17 Nov 2015 21:08:07 -0500 Subject: XEEN: Merge Clouds and DarkSide engines into WorldOfXeenEngine --- engines/xeen/clouds/clouds_game.cpp | 38 ----- engines/xeen/clouds/clouds_game.h | 42 ----- engines/xeen/darkside/darkside_game.cpp | 228 -------------------------- engines/xeen/darkside/darkside_game.h | 50 ------ engines/xeen/detection.cpp | 6 - engines/xeen/module.mk | 2 - engines/xeen/worldofxeen/worldofxeen_game.cpp | 183 ++++++++++++++++++++- engines/xeen/worldofxeen/worldofxeen_game.h | 30 +++- 8 files changed, 208 insertions(+), 371 deletions(-) delete mode 100644 engines/xeen/clouds/clouds_game.cpp delete mode 100644 engines/xeen/clouds/clouds_game.h delete mode 100644 engines/xeen/darkside/darkside_game.cpp delete mode 100644 engines/xeen/darkside/darkside_game.h (limited to 'engines/xeen') diff --git a/engines/xeen/clouds/clouds_game.cpp b/engines/xeen/clouds/clouds_game.cpp deleted file mode 100644 index 4987ce05dd..0000000000 --- a/engines/xeen/clouds/clouds_game.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* 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 "xeen/clouds/clouds_game.h" - -namespace Xeen { - -CloudsEngine::CloudsEngine(OSystem *syst, const XeenGameDescription *gameDesc) - : XeenEngine(syst, gameDesc) { -} - -void CloudsEngine::playGame() { - cloudsIntro(); -} - -void CloudsEngine::cloudsIntro() { -} - -} // End of namespace Xeen diff --git a/engines/xeen/clouds/clouds_game.h b/engines/xeen/clouds/clouds_game.h deleted file mode 100644 index a8c4fbea3b..0000000000 --- a/engines/xeen/clouds/clouds_game.h +++ /dev/null @@ -1,42 +0,0 @@ -/* 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 XEEN_CLOUDS_GAME_H -#define XEEN_CLOUDS_GAME_H - -#include "xeen/xeen.h" - -namespace Xeen { - -class CloudsEngine : virtual public XeenEngine { -protected: - void cloudsIntro(); - - virtual void playGame(); -public: - CloudsEngine(OSystem *syst, const XeenGameDescription *gameDesc); - virtual ~CloudsEngine() {} -}; - -} // End of namespace Xeen - -#endif /* XEEN_CLOUDS_GAME_H */ diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp deleted file mode 100644 index fe8c161287..0000000000 --- a/engines/xeen/darkside/darkside_game.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* 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 "xeen/darkside/darkside_game.h" -#include "xeen/resources.h" -#include "xeen/screen.h" - -namespace Xeen { - -DarkSideEngine::DarkSideEngine(OSystem *syst, const XeenGameDescription *gameDesc) - : XeenEngine(syst, gameDesc) { -} - -void DarkSideEngine::playGame() { - // TODO -} - -bool DarkSideEngine::pause(uint amount) { - while (!shouldQuit() && _events->timeElapsed() < amount) { - _events->pollEventsAndWait(); - if (_events->isKeyMousePressed()) - return true; - } - - return shouldQuit(); -} - -void DarkSideEngine::darkSideIntro() { - /* - showTitle1(); - if (shouldQuit()) - return; - - showTitle2(); - if (shouldQuit()) - return; - */ - // TODO: Only show startup if not seen before - showStartSequence(); -} - -void DarkSideEngine::showTitle1() { - // TODO: Starting method, and sound - //sub_28F40 - _screen->loadPalette("dark.pal"); - SpriteResource nwc[4] = { - SpriteResource("nwc1.int"), SpriteResource("nwc2.int"), - SpriteResource("nwc3.int"), SpriteResource("nwc4.int") - }; - Common::File voc[3]; - voc[0].open("dragon1.voc"); - voc[1].open("dragon2.voc"); - voc[2].open("dragon3.voc"); - - // Load backgrounds - _screen->loadBackground("nwc1.raw"); - _screen->loadPage(0); - _screen->loadBackground("nwc2.raw"); - _screen->loadPage(1); - - // Draw the screen and fade it in - _screen->horizMerge(0); - _screen->draw(); - _screen->fadeIn(4); - - // Initial loop for dragon roaring - int nwcIndex = 0, nwcFrame = 0; - for (int idx = 0; idx < 55 && !shouldQuit(); ++idx) { - // Render the next frame - _events->updateGameCounter(); - _screen->vertMerge(0); - nwc[nwcIndex].draw(*_screen, nwcFrame); - _screen->draw(); - - switch (idx) { - case 17: - _sound->proc2(voc[0]); - break; - case 34: - case 44: - ++nwcIndex; - nwcFrame = 0; - break; - case 35: - _sound->proc2(voc[1]); - break; - default: - ++nwcFrame; - } - - if (pause(2)) - return; - } - - // Loop for dragon using flyspray - for (int idx = 0; idx < 42 && !shouldQuit(); ++idx) { - _events->updateGameCounter(); - _screen->vertMerge(SCREEN_HEIGHT); - nwc[3].draw(*_screen, idx); - _screen->draw(); - - switch (idx) { - case 3: - _sound->startMusic(40); - break; - case 11: - _sound->startMusic(0); - case 27: - case 30: - _sound->startMusic(3); - break; - case 31: - _sound->proc2(voc[2]); - break; - case 33: - _sound->startMusic(2); - break; - default: - break; - } - - if (pause(2)) - return; - } - - // Pause for a bit - pause(10); -} - -void DarkSideEngine::showTitle2() { - _screen->fadeOut(8); - //TODO: Stuff - - _screen->loadBackground("jvc.raw"); - _screen->draw(); - _screen->fadeIn(4); - - _events->updateGameCounter(); - pause(60); -} - -void DarkSideEngine::showStartSequence() { - _screen->fadeOut(8); - _screen->loadBackground("pyramid2.raw"); - _screen->loadPage(0); - _screen->loadPage(1); - _screen->loadBackground("pyramid3.raw"); - _screen->saveBackground(1); - - SpriteResource sprites[3] = { - SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int") - }; - Common::File voc[2]; - voc[0].open("pharoh1a.voc"); - voc[1].open("pharoh1b.voc"); - - _screen->vertMerge(SCREEN_HEIGHT); - _screen->loadPage(0); - _screen->loadPage(1); - - int yp = 0; - int frame = 0; - int idx1 = 0; - bool skipElapsed = false; - uint32 timeExpired = 0; -// bool fadeFlag = true; - - for (int idx = 200; idx > 0; ) { - _events->updateGameCounter(); - _screen->vertMerge(yp); - - sprites[0].draw(*_screen, 0); - if (frame) - sprites[0].draw(*_screen, frame); - - idx1 = (idx1 + 1) % 4; - if (!idx1) - frame = (frame + 1) % 10; - - _screen->draw(); - if (!skipElapsed) { - timeExpired = MAX(_events->timeElapsed(), (uint32)1); - skipElapsed = true; - } - - idx -= timeExpired; - frame = MIN(frame + timeExpired, (uint)200); - - while (_events->timeElapsed() < 1) { - _events->pollEventsAndWait(); - if (_events->isKeyMousePressed()) - return; - } - } - - _screen->vertMerge(SCREEN_HEIGHT); - _screen->saveBackground(1); - _screen->draw(); - _screen->freePages(); - - _events->updateGameCounter(); - pause(30); - - // TODO: More - _sound->playSong(voc[0]); - _sound->playSong(voc[1]); -} - -} // End of namespace Xeen diff --git a/engines/xeen/darkside/darkside_game.h b/engines/xeen/darkside/darkside_game.h deleted file mode 100644 index 979885cc13..0000000000 --- a/engines/xeen/darkside/darkside_game.h +++ /dev/null @@ -1,50 +0,0 @@ -/* 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 XEEN_DARKSIDE_GAME_H -#define XEEN_DARKSIDE_GAME_H - -#include "xeen/xeen.h" - -namespace Xeen { - -class DarkSideEngine : virtual public XeenEngine { -private: - bool pause(uint amount); - - void showTitle1(); - - void showTitle2(); - - void showStartSequence(); -protected: - void darkSideIntro(); - - virtual void playGame(); -public: - DarkSideEngine(OSystem *syst, const XeenGameDescription *gameDesc); - virtual ~DarkSideEngine() {} -}; - -} // End of namespace Xeen - -#endif /* XEEN_DARKSIDE_GAME_H */ diff --git a/engines/xeen/detection.cpp b/engines/xeen/detection.cpp index 3bd4c22f97..64b28bf687 100644 --- a/engines/xeen/detection.cpp +++ b/engines/xeen/detection.cpp @@ -21,8 +21,6 @@ */ #include "xeen/xeen.h" -#include "xeen/clouds/clouds_game.h" -#include "xeen/darkside/darkside_game.h" #include "xeen/worldofxeen/worldofxeen_game.h" #include "base/plugins.h" @@ -116,11 +114,7 @@ bool XeenMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGame switch (gd->gameID) { case Xeen::GType_Clouds: - *engine = new Xeen::CloudsEngine(syst, gd); - break; case Xeen::GType_DarkSide: - *engine = new Xeen::DarkSideEngine(syst, gd); - break; case Xeen::GType_WorldOfXeen: *engine = new Xeen::WorldOfXeenEngine(syst, gd); break; diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 4e64b8e815..711be847d1 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -1,8 +1,6 @@ MODULE := engines/xeen MODULE_OBJS := \ - clouds/clouds_game.o \ - darkside/darkside_game.o \ worldofxeen/worldofxeen_game.o \ character.o \ combat.o \ diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp index bcfbaa1675..3b0efb2aac 100644 --- a/engines/xeen/worldofxeen/worldofxeen_game.cpp +++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp @@ -25,12 +25,191 @@ namespace Xeen { WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) - : CloudsEngine(syst, gameDesc), DarkSideEngine(syst, gameDesc), - XeenEngine(syst, gameDesc) { + : XeenEngine(syst, gameDesc) { } void WorldOfXeenEngine::playGame () { XeenEngine::playGame(); } +void WorldOfXeenEngine::showDarkSideTitle() { + showDarkSideTitle1(); + if (shouldQuit()) + return; + + showDarkSideTitle2(); + if (shouldQuit()) + return; + + // TODO: Only show intro sequence if not seen before + showDarkSideIntroSequence(); +} + +void WorldOfXeenEngine::showDarkSideTitle1() { + // TODO: Starting method, and sound + //sub_28F40 + _screen->loadPalette("dark.pal"); + SpriteResource nwc[4] = { + SpriteResource("nwc1.int"), SpriteResource("nwc2.int"), + SpriteResource("nwc3.int"), SpriteResource("nwc4.int") + }; + Common::File voc[3]; + voc[0].open("dragon1.voc"); + voc[1].open("dragon2.voc"); + voc[2].open("dragon3.voc"); + + // Load backgrounds + _screen->loadBackground("nwc1.raw"); + _screen->loadPage(0); + _screen->loadBackground("nwc2.raw"); + _screen->loadPage(1); + + // Draw the screen and fade it in + _screen->horizMerge(0); + _screen->draw(); + _screen->fadeIn(4); + + // Initial loop for dragon roaring + int nwcIndex = 0, nwcFrame = 0; + for (int idx = 0; idx < 55 && !shouldQuit(); ++idx) { + // Render the next frame + _events->updateGameCounter(); + _screen->vertMerge(0); + nwc[nwcIndex].draw(*_screen, nwcFrame); + _screen->draw(); + + switch (idx) { + case 17: + _sound->proc2(voc[0]); + break; + case 34: + case 44: + ++nwcIndex; + nwcFrame = 0; + break; + case 35: + _sound->proc2(voc[1]); + break; + default: + ++nwcFrame; + } + + if (_events->wait(2, true)) + return; + } + + // Loop for dragon using flyspray + for (int idx = 0; idx < 42 && !shouldQuit(); ++idx) { + _events->updateGameCounter(); + _screen->vertMerge(SCREEN_HEIGHT); + nwc[3].draw(*_screen, idx); + _screen->draw(); + + switch (idx) { + case 3: + _sound->startMusic(40); + break; + case 11: + _sound->startMusic(0); + case 27: + case 30: + _sound->startMusic(3); + break; + case 31: + _sound->proc2(voc[2]); + break; + case 33: + _sound->startMusic(2); + break; + default: + break; + } + + if (_events->wait(2, true)) + return; + } + + // Pause for a bit + _events->wait(10, true); +} + +void WorldOfXeenEngine::showDarkSideTitle2() { + _screen->fadeOut(8); + //TODO: Stuff + + _screen->loadBackground("jvc.raw"); + _screen->draw(); + _screen->fadeIn(4); + + _events->updateGameCounter(); + _events->wait(60, true); +} + +void WorldOfXeenEngine::showDarkSideIntroSequence() { + _screen->fadeOut(8); + _screen->loadBackground("pyramid2.raw"); + _screen->loadPage(0); + _screen->loadPage(1); + _screen->loadBackground("pyramid3.raw"); + _screen->saveBackground(1); + + SpriteResource sprites[3] = { + SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int") + }; + Common::File voc[2]; + voc[0].open("pharoh1a.voc"); + voc[1].open("pharoh1b.voc"); + + _screen->vertMerge(SCREEN_HEIGHT); + _screen->loadPage(0); + _screen->loadPage(1); + + int yp = 0; + int frame = 0; + int idx1 = 0; + bool skipElapsed = false; + uint32 timeExpired = 0; + // bool fadeFlag = true; + + for (int idx = 200; idx > 0; ) { + _events->updateGameCounter(); + _screen->vertMerge(yp); + + sprites[0].draw(*_screen, 0); + if (frame) + sprites[0].draw(*_screen, frame); + + idx1 = (idx1 + 1) % 4; + if (!idx1) + frame = (frame + 1) % 10; + + _screen->draw(); + if (!skipElapsed) { + timeExpired = MAX(_events->timeElapsed(), (uint32)1); + skipElapsed = true; + } + + idx -= timeExpired; + frame = MIN(frame + timeExpired, (uint)200); + + while (_events->timeElapsed() < 1) { + _events->pollEventsAndWait(); + if (_events->isKeyMousePressed()) + return; + } + } + + _screen->vertMerge(SCREEN_HEIGHT); + _screen->saveBackground(1); + _screen->draw(); + _screen->freePages(); + + _events->updateGameCounter(); + _events->wait(30, true); + + // TODO: More + _sound->playSong(voc[0]); + _sound->playSong(voc[1]); +} + } // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/worldofxeen_game.h b/engines/xeen/worldofxeen/worldofxeen_game.h index 7227e11fc4..9a3cee185d 100644 --- a/engines/xeen/worldofxeen/worldofxeen_game.h +++ b/engines/xeen/worldofxeen/worldofxeen_game.h @@ -23,12 +23,36 @@ #ifndef XEEN_WORLDOFXEEN_GAME_H #define XEEN_WORLDOFXEEN_GAME_H -#include "xeen/clouds/clouds_game.h" -#include "xeen/darkside/darkside_game.h" +#include "xeen/xeen.h" namespace Xeen { -class WorldOfXeenEngine : public DarkSideEngine, CloudsEngine { +/** + * Implements a descendant of the base Xeen engine to handle + * Clouds of Xeen, Dark Side of Xeen, and Worlds of Xeen specific + * game code + */ +class WorldOfXeenEngine: public XeenEngine { +private: + /** + * Shows the first part of the Dark Side of Xeen title sequence + */ + void showDarkSideTitle1(); + + /** + * Shows the second part of the Dark Side of Xeen title sequence + */ + void showDarkSideTitle2(); + + /** + * Shows the Dark Side of Xeen title sequence + */ + void showDarkSideTitle(); + + /** + * Shows the Dark Side of Xeen introduction sequence + */ + void showDarkSideIntroSequence(); protected: virtual void playGame(); public: -- cgit v1.2.3 From b6e39dbf79801b5d96ca9292a47825d39f1e3fb4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 20 Nov 2015 20:11:23 -0500 Subject: XEEN: Some initial work on better sound manager --- engines/xeen/sound.cpp | 12 ++++++ engines/xeen/sound.h | 15 ++++++++ engines/xeen/worldofxeen/worldofxeen_game.cpp | 55 ++++++++++++++++----------- engines/xeen/worldofxeen/worldofxeen_game.h | 14 +------ engines/xeen/xeen.cpp | 4 -- engines/xeen/xeen.h | 4 +- 6 files changed, 64 insertions(+), 40 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp index 7c7524af54..a71584c769 100644 --- a/engines/xeen/sound.cpp +++ b/engines/xeen/sound.cpp @@ -24,6 +24,18 @@ namespace Xeen { +VOC::~VOC() { + stop(); +} + +void VOC::play() { + warning("TODO: VOC::play"); +} + +void VOC::stop() { + warning("TODO: VOC::stop"); +} + SoundManager::SoundManager(XeenEngine *vm): _vm(vm) { } diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index 7e7df9caea..b44bff7f30 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -29,6 +29,21 @@ namespace Xeen { +class VOC: public Common::File { +public: + virtual ~VOC(); + + /** + * Play the given loaded sound + */ + void play(); + + /** + * Stop playing the sound + */ + void stop(); +}; + class SoundManager { private: XeenEngine *_vm; diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp index 3b0efb2aac..836f039cf6 100644 --- a/engines/xeen/worldofxeen/worldofxeen_game.cpp +++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp @@ -21,6 +21,7 @@ */ #include "xeen/worldofxeen/worldofxeen_game.h" +#include "xeen/sound.h" namespace Xeen { @@ -28,24 +29,15 @@ WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *g : XeenEngine(syst, gameDesc) { } -void WorldOfXeenEngine::playGame () { - XeenEngine::playGame(); -} - -void WorldOfXeenEngine::showDarkSideTitle() { - showDarkSideTitle1(); - if (shouldQuit()) - return; +void WorldOfXeenEngine::showIntro() { + // **DEBUG** + if (gDebugLevel == 0) + return; - showDarkSideTitle2(); - if (shouldQuit()) - return; - - // TODO: Only show intro sequence if not seen before - showDarkSideIntroSequence(); + showDarkSideTitle(); } -void WorldOfXeenEngine::showDarkSideTitle1() { +void WorldOfXeenEngine::showDarkSideTitle() { // TODO: Starting method, and sound //sub_28F40 _screen->loadPalette("dark.pal"); @@ -53,11 +45,22 @@ void WorldOfXeenEngine::showDarkSideTitle1() { SpriteResource("nwc1.int"), SpriteResource("nwc2.int"), SpriteResource("nwc3.int"), SpriteResource("nwc4.int") }; - Common::File voc[3]; + VOC voc[3]; voc[0].open("dragon1.voc"); voc[1].open("dragon2.voc"); voc[2].open("dragon3.voc"); - +/* + Common::File f; + f.open("adsnd"); + Common::DumpFile df; + byte *b = new byte[f.size()]; + f.read(b, f.size()); + df.open("d:\\temp\\adsnd.bin"); + df.write(b, f.size()); + df.close(); + f.close(); + delete[] b; + */ // Load backgrounds _screen->loadBackground("nwc1.raw"); _screen->loadPage(0); @@ -97,6 +100,8 @@ void WorldOfXeenEngine::showDarkSideTitle1() { if (_events->wait(2, true)) return; } + if (shouldQuit()) + return; // Loop for dragon using flyspray for (int idx = 0; idx < 42 && !shouldQuit(); ++idx) { @@ -130,10 +135,16 @@ void WorldOfXeenEngine::showDarkSideTitle1() { } // Pause for a bit - _events->wait(10, true); -} + if (_events->wait(10, true)) + return; + if (shouldQuit()) + return; + + voc[0].stop(); + voc[1].stop(); + voc[2].stop(); + -void WorldOfXeenEngine::showDarkSideTitle2() { _screen->fadeOut(8); //TODO: Stuff @@ -145,7 +156,7 @@ void WorldOfXeenEngine::showDarkSideTitle2() { _events->wait(60, true); } -void WorldOfXeenEngine::showDarkSideIntroSequence() { +void WorldOfXeenEngine::showDarkSideIntro() { _screen->fadeOut(8); _screen->loadBackground("pyramid2.raw"); _screen->loadPage(0); @@ -191,7 +202,7 @@ void WorldOfXeenEngine::showDarkSideIntroSequence() { idx -= timeExpired; frame = MIN(frame + timeExpired, (uint)200); - + while (_events->timeElapsed() < 1) { _events->pollEventsAndWait(); if (_events->isKeyMousePressed()) diff --git a/engines/xeen/worldofxeen/worldofxeen_game.h b/engines/xeen/worldofxeen/worldofxeen_game.h index 9a3cee185d..f35f25be15 100644 --- a/engines/xeen/worldofxeen/worldofxeen_game.h +++ b/engines/xeen/worldofxeen/worldofxeen_game.h @@ -34,16 +34,6 @@ namespace Xeen { */ class WorldOfXeenEngine: public XeenEngine { private: - /** - * Shows the first part of the Dark Side of Xeen title sequence - */ - void showDarkSideTitle1(); - - /** - * Shows the second part of the Dark Side of Xeen title sequence - */ - void showDarkSideTitle2(); - /** * Shows the Dark Side of Xeen title sequence */ @@ -52,9 +42,9 @@ private: /** * Shows the Dark Side of Xeen introduction sequence */ - void showDarkSideIntroSequence(); + void showDarkSideIntro(); protected: - virtual void playGame(); + virtual void showIntro(); public: WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); virtual ~WorldOfXeenEngine() {} diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index fb7edead00..90349858ee 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -266,10 +266,6 @@ void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeade // out->writeUint32LE(_events->getFrameCounter()); } -void XeenEngine::showIntro() { - -} - void XeenEngine::showMainMenu() { //OptionsMenu::show(this); } diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 4180a17650..cd1b98b1b8 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -104,8 +104,6 @@ private: Common::RandomSource _randomSource; int _loadSaveSlot; - void showIntro(); - void showMainMenu(); void play(); @@ -114,6 +112,8 @@ private: void gameLoop(); protected: + virtual void showIntro() = 0; + /** * Play the game */ -- cgit v1.2.3 From 0ade2da5f1647ae1942a2a3e7aa26f219e5b7a2d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Nov 2015 14:34:08 -0500 Subject: XEEN: Further work on VOC sound method prototypes --- engines/xeen/sound.h | 15 +++++++++------ engines/xeen/worldofxeen/worldofxeen_game.cpp | 4 ++-- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index b44bff7f30..fae3d76dba 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -29,14 +29,15 @@ namespace Xeen { +class SoundManager; + class VOC: public Common::File { + friend class SoundManager; +private: + SoundManager *_sound; public: - virtual ~VOC(); - - /** - * Play the given loaded sound - */ - void play(); + VOC() : _sound(nullptr) {} + virtual ~VOC() { stop(); } /** * Stop playing the sound @@ -58,6 +59,8 @@ public: void playSong(Common::SeekableReadStream &f) {} + void playSound(VOC &voc) {} + void playSample(const Common::SeekableReadStream *stream, int v2 = 1) {} bool playSample(int v1, int v2) { return false; } diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp index 836f039cf6..665507d915 100644 --- a/engines/xeen/worldofxeen/worldofxeen_game.cpp +++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp @@ -83,7 +83,7 @@ void WorldOfXeenEngine::showDarkSideTitle() { switch (idx) { case 17: - _sound->proc2(voc[0]); + _sound->playSound(voc[0]); break; case 34: case 44: @@ -91,7 +91,7 @@ void WorldOfXeenEngine::showDarkSideTitle() { nwcFrame = 0; break; case 35: - _sound->proc2(voc[1]); + _sound->playSound(voc[1]); break; default: ++nwcFrame; -- cgit v1.2.3 From 82117272854a11ecd2ed5db1c7715de7f15f96c0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Nov 2015 16:22:50 -0500 Subject: XEEN: Remove duplicate methods --- engines/xeen/sound.cpp | 8 -------- 1 file changed, 8 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp index a71584c769..e0b12215ce 100644 --- a/engines/xeen/sound.cpp +++ b/engines/xeen/sound.cpp @@ -24,14 +24,6 @@ namespace Xeen { -VOC::~VOC() { - stop(); -} - -void VOC::play() { - warning("TODO: VOC::play"); -} - void VOC::stop() { warning("TODO: VOC::stop"); } -- cgit v1.2.3 From 9c92f9fa476219b7c775676565d7b3ebdd8d2c1e Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 29 Nov 2015 11:34:28 -0500 Subject: XEEN: Moved in-progress Dark Side intro to it's own file --- engines/xeen/module.mk | 1 + engines/xeen/worldofxeen/darkside_intro.cpp | 222 ++++++++++++++++++++++++++ engines/xeen/worldofxeen/darkside_intro.h | 36 +++++ engines/xeen/worldofxeen/worldofxeen_game.cpp | 189 +--------------------- engines/xeen/worldofxeen/worldofxeen_game.h | 10 -- 5 files changed, 261 insertions(+), 197 deletions(-) create mode 100644 engines/xeen/worldofxeen/darkside_intro.cpp create mode 100644 engines/xeen/worldofxeen/darkside_intro.h (limited to 'engines/xeen') diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 711be847d1..a1e62e149f 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -1,6 +1,7 @@ MODULE := engines/xeen MODULE_OBJS := \ + worldofxeen/darkside_intro.o \ worldofxeen/worldofxeen_game.o \ character.o \ combat.o \ diff --git a/engines/xeen/worldofxeen/darkside_intro.cpp b/engines/xeen/worldofxeen/darkside_intro.cpp new file mode 100644 index 0000000000..2d284c1581 --- /dev/null +++ b/engines/xeen/worldofxeen/darkside_intro.cpp @@ -0,0 +1,222 @@ +/* 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 "xeen/worldofxeen/worldofxeen_game.h" +#include "xeen/sound.h" + +namespace Xeen { + +void showDarkSideTitle(XeenEngine &vm) { + EventsManager &events = *vm._events; + Screen &screen = *vm._screen; + SoundManager &sound = *vm._sound; + + // TODO: Starting method, and sound + //sub_28F40 + screen.loadPalette("dark.pal"); + SpriteResource nwc[4] = { + SpriteResource("nwc1.int"), SpriteResource("nwc2.int"), + SpriteResource("nwc3.int"), SpriteResource("nwc4.int") + }; + VOC voc[3]; + voc[0].open("dragon1.voc"); + voc[1].open("dragon2.voc"); + voc[2].open("dragon3.voc"); +/* + Common::File f; + f.open("adsnd"); + Common::DumpFile df; + byte *b = new byte[f.size()]; + f.read(b, f.size()); + df.open("d:\\temp\\adsnd.bin"); + df.write(b, f.size()); + df.close(); + f.close(); + delete[] b; + */ + // Load backgrounds + screen.loadBackground("nwc1.raw"); + screen.loadPage(0); + screen.loadBackground("nwc2.raw"); + screen.loadPage(1); + + // Draw the screen and fade it in + screen.horizMerge(0); + screen.draw(); + screen.fadeIn(4); + + // Initial loop for dragon roaring + int nwcIndex = 0, nwcFrame = 0; + for (int idx = 0; idx < 55 && !vm.shouldQuit(); ++idx) { + // Render the next frame + events.updateGameCounter(); + screen.vertMerge(0); + nwc[nwcIndex].draw(screen, nwcFrame); + screen.draw(); + + switch (idx) { + case 17: + sound.playSound(voc[0]); + break; + case 34: + case 44: + ++nwcIndex; + nwcFrame = 0; + break; + case 35: + sound.playSound(voc[1]); + break; + default: + ++nwcFrame; + } + + if (events.wait(2, true)) + return; + } + if (vm.shouldQuit()) + return; + + // Loop for dragon using flyspray + for (int idx = 0; idx < 42 && !vm.shouldQuit(); ++idx) { + events.updateGameCounter(); + screen.vertMerge(SCREEN_HEIGHT); + nwc[3].draw(screen, idx); + screen.draw(); + + switch (idx) { + case 3: + sound.startMusic(40); + break; + case 11: + sound.startMusic(0); + case 27: + case 30: + sound.startMusic(3); + break; + case 31: + sound.proc2(voc[2]); + break; + case 33: + sound.startMusic(2); + break; + default: + break; + } + + if (events.wait(2, true)) + return; + } + + // Pause for a bit + if (events.wait(10, true)) + return; + if (vm.shouldQuit()) + return; + + voc[0].stop(); + voc[1].stop(); + voc[2].stop(); + + + screen.fadeOut(8); + //TODO: Stuff + + screen.loadBackground("jvc.raw"); + screen.draw(); + screen.fadeIn(4); + + events.updateGameCounter(); + events.wait(60, true); +} + +void showDarkSideIntro(XeenEngine &vm) { + EventsManager &events = *vm._events; + Screen &screen = *vm._screen; + SoundManager &sound = *vm._sound; + + screen.fadeOut(8); + screen.loadBackground("pyramid2.raw"); + screen.loadPage(0); + screen.loadPage(1); + screen.loadBackground("pyramid3.raw"); + screen.saveBackground(1); + + SpriteResource sprites[3] = { + SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int") + }; + Common::File voc[2]; + voc[0].open("pharoh1a.voc"); + voc[1].open("pharoh1b.voc"); + + screen.vertMerge(SCREEN_HEIGHT); + screen.loadPage(0); + screen.loadPage(1); + + int yp = 0; + int frame = 0; + int idx1 = 0; + bool skipElapsed = false; + uint32 timeExpired = 0; + // bool fadeFlag = true; + + for (int idx = 200; idx > 0; ) { + events.updateGameCounter(); + screen.vertMerge(yp); + + sprites[0].draw(screen, 0); + if (frame) + sprites[0].draw(screen, frame); + + idx1 = (idx1 + 1) % 4; + if (!idx1) + frame = (frame + 1) % 10; + + screen.draw(); + if (!skipElapsed) { + timeExpired = MAX(events.timeElapsed(), (uint32)1); + skipElapsed = true; + } + + idx -= timeExpired; + frame = MIN(frame + timeExpired, (uint)200); + + while (events.timeElapsed() < 1) { + events.pollEventsAndWait(); + if (events.isKeyMousePressed()) + return; + } + } + + screen.vertMerge(SCREEN_HEIGHT); + screen.saveBackground(1); + screen.draw(); + screen.freePages(); + + events.updateGameCounter(); + events.wait(30, true); + + // TODO: More + sound.playSong(voc[0]); + sound.playSong(voc[1]); +} + +} // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/darkside_intro.h b/engines/xeen/worldofxeen/darkside_intro.h new file mode 100644 index 0000000000..535ee21b39 --- /dev/null +++ b/engines/xeen/worldofxeen/darkside_intro.h @@ -0,0 +1,36 @@ +/* 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 XEEN_DARKSIDE_INTRO_H +#define XEEN_DARKSIDE_INTRO_H + +#include "xeen/xeen.h" + +namespace Xeen { + +void showDarkSideTitle(XeenEngine &vm); + +void showDarkSideIntro(XeenEngine &vm); + +} // End of namespace Xeen + +#endif /* XEEN_DARKSIDE_INTRO_H */ diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp index 665507d915..125f9f26c6 100644 --- a/engines/xeen/worldofxeen/worldofxeen_game.cpp +++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp @@ -21,6 +21,7 @@ */ #include "xeen/worldofxeen/worldofxeen_game.h" +#include "xeen/worldofxeen/darkside_intro.h" #include "xeen/sound.h" namespace Xeen { @@ -34,193 +35,7 @@ void WorldOfXeenEngine::showIntro() { if (gDebugLevel == 0) return; - showDarkSideTitle(); -} - -void WorldOfXeenEngine::showDarkSideTitle() { - // TODO: Starting method, and sound - //sub_28F40 - _screen->loadPalette("dark.pal"); - SpriteResource nwc[4] = { - SpriteResource("nwc1.int"), SpriteResource("nwc2.int"), - SpriteResource("nwc3.int"), SpriteResource("nwc4.int") - }; - VOC voc[3]; - voc[0].open("dragon1.voc"); - voc[1].open("dragon2.voc"); - voc[2].open("dragon3.voc"); -/* - Common::File f; - f.open("adsnd"); - Common::DumpFile df; - byte *b = new byte[f.size()]; - f.read(b, f.size()); - df.open("d:\\temp\\adsnd.bin"); - df.write(b, f.size()); - df.close(); - f.close(); - delete[] b; - */ - // Load backgrounds - _screen->loadBackground("nwc1.raw"); - _screen->loadPage(0); - _screen->loadBackground("nwc2.raw"); - _screen->loadPage(1); - - // Draw the screen and fade it in - _screen->horizMerge(0); - _screen->draw(); - _screen->fadeIn(4); - - // Initial loop for dragon roaring - int nwcIndex = 0, nwcFrame = 0; - for (int idx = 0; idx < 55 && !shouldQuit(); ++idx) { - // Render the next frame - _events->updateGameCounter(); - _screen->vertMerge(0); - nwc[nwcIndex].draw(*_screen, nwcFrame); - _screen->draw(); - - switch (idx) { - case 17: - _sound->playSound(voc[0]); - break; - case 34: - case 44: - ++nwcIndex; - nwcFrame = 0; - break; - case 35: - _sound->playSound(voc[1]); - break; - default: - ++nwcFrame; - } - - if (_events->wait(2, true)) - return; - } - if (shouldQuit()) - return; - - // Loop for dragon using flyspray - for (int idx = 0; idx < 42 && !shouldQuit(); ++idx) { - _events->updateGameCounter(); - _screen->vertMerge(SCREEN_HEIGHT); - nwc[3].draw(*_screen, idx); - _screen->draw(); - - switch (idx) { - case 3: - _sound->startMusic(40); - break; - case 11: - _sound->startMusic(0); - case 27: - case 30: - _sound->startMusic(3); - break; - case 31: - _sound->proc2(voc[2]); - break; - case 33: - _sound->startMusic(2); - break; - default: - break; - } - - if (_events->wait(2, true)) - return; - } - - // Pause for a bit - if (_events->wait(10, true)) - return; - if (shouldQuit()) - return; - - voc[0].stop(); - voc[1].stop(); - voc[2].stop(); - - - _screen->fadeOut(8); - //TODO: Stuff - - _screen->loadBackground("jvc.raw"); - _screen->draw(); - _screen->fadeIn(4); - - _events->updateGameCounter(); - _events->wait(60, true); -} - -void WorldOfXeenEngine::showDarkSideIntro() { - _screen->fadeOut(8); - _screen->loadBackground("pyramid2.raw"); - _screen->loadPage(0); - _screen->loadPage(1); - _screen->loadBackground("pyramid3.raw"); - _screen->saveBackground(1); - - SpriteResource sprites[3] = { - SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int") - }; - Common::File voc[2]; - voc[0].open("pharoh1a.voc"); - voc[1].open("pharoh1b.voc"); - - _screen->vertMerge(SCREEN_HEIGHT); - _screen->loadPage(0); - _screen->loadPage(1); - - int yp = 0; - int frame = 0; - int idx1 = 0; - bool skipElapsed = false; - uint32 timeExpired = 0; - // bool fadeFlag = true; - - for (int idx = 200; idx > 0; ) { - _events->updateGameCounter(); - _screen->vertMerge(yp); - - sprites[0].draw(*_screen, 0); - if (frame) - sprites[0].draw(*_screen, frame); - - idx1 = (idx1 + 1) % 4; - if (!idx1) - frame = (frame + 1) % 10; - - _screen->draw(); - if (!skipElapsed) { - timeExpired = MAX(_events->timeElapsed(), (uint32)1); - skipElapsed = true; - } - - idx -= timeExpired; - frame = MIN(frame + timeExpired, (uint)200); - - while (_events->timeElapsed() < 1) { - _events->pollEventsAndWait(); - if (_events->isKeyMousePressed()) - return; - } - } - - _screen->vertMerge(SCREEN_HEIGHT); - _screen->saveBackground(1); - _screen->draw(); - _screen->freePages(); - - _events->updateGameCounter(); - _events->wait(30, true); - - // TODO: More - _sound->playSong(voc[0]); - _sound->playSong(voc[1]); + showDarkSideTitle(*this); } } // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/worldofxeen_game.h b/engines/xeen/worldofxeen/worldofxeen_game.h index f35f25be15..f81f566d88 100644 --- a/engines/xeen/worldofxeen/worldofxeen_game.h +++ b/engines/xeen/worldofxeen/worldofxeen_game.h @@ -33,16 +33,6 @@ namespace Xeen { * game code */ class WorldOfXeenEngine: public XeenEngine { -private: - /** - * Shows the Dark Side of Xeen title sequence - */ - void showDarkSideTitle(); - - /** - * Shows the Dark Side of Xeen introduction sequence - */ - void showDarkSideIntro(); protected: virtual void showIntro(); public: -- cgit v1.2.3 From 5b0f460581e9deb08fc0f66e8faeb356f31c2ae5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 29 Nov 2015 22:32:07 -0500 Subject: XEEN: Implementing more of Dark Side intro --- engines/xeen/sound.cpp | 3 + engines/xeen/sound.h | 2 + engines/xeen/worldofxeen/darkside_intro.cpp | 88 +++++++++++++++------------ engines/xeen/worldofxeen/darkside_intro.h | 4 +- engines/xeen/worldofxeen/worldofxeen_game.cpp | 5 +- engines/xeen/worldofxeen/worldofxeen_game.h | 2 + 6 files changed, 63 insertions(+), 41 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp index e0b12215ce..00b92472cc 100644 --- a/engines/xeen/sound.cpp +++ b/engines/xeen/sound.cpp @@ -39,5 +39,8 @@ void SoundManager::startMusic(int v1) { } +void SoundManager::stopMusic(int id) { +} + } // End of namespace Xeen diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index fae3d76dba..5c123d7d89 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -57,6 +57,8 @@ public: void startMusic(int v1); + void stopMusic(int id); + void playSong(Common::SeekableReadStream &f) {} void playSound(VOC &voc) {} diff --git a/engines/xeen/worldofxeen/darkside_intro.cpp b/engines/xeen/worldofxeen/darkside_intro.cpp index 2d284c1581..8148e249d0 100644 --- a/engines/xeen/worldofxeen/darkside_intro.cpp +++ b/engines/xeen/worldofxeen/darkside_intro.cpp @@ -25,7 +25,7 @@ namespace Xeen { -void showDarkSideTitle(XeenEngine &vm) { +bool showDarkSideTitle(XeenEngine &vm) { EventsManager &events = *vm._events; Screen &screen = *vm._screen; SoundManager &sound = *vm._sound; @@ -41,18 +41,7 @@ void showDarkSideTitle(XeenEngine &vm) { voc[0].open("dragon1.voc"); voc[1].open("dragon2.voc"); voc[2].open("dragon3.voc"); -/* - Common::File f; - f.open("adsnd"); - Common::DumpFile df; - byte *b = new byte[f.size()]; - f.read(b, f.size()); - df.open("d:\\temp\\adsnd.bin"); - df.write(b, f.size()); - df.close(); - f.close(); - delete[] b; - */ + // Load backgrounds screen.loadBackground("nwc1.raw"); screen.loadPage(0); @@ -90,10 +79,8 @@ void showDarkSideTitle(XeenEngine &vm) { } if (events.wait(2, true)) - return; + return false; } - if (vm.shouldQuit()) - return; // Loop for dragon using flyspray for (int idx = 0; idx < 42 && !vm.shouldQuit(); ++idx) { @@ -123,35 +110,41 @@ void showDarkSideTitle(XeenEngine &vm) { } if (events.wait(2, true)) - return; + return false; } // Pause for a bit if (events.wait(10, true)) - return; - if (vm.shouldQuit()) - return; + return false; voc[0].stop(); voc[1].stop(); voc[2].stop(); - - - screen.fadeOut(8); - //TODO: Stuff + sound.stopMusic(95); screen.loadBackground("jvc.raw"); + screen.fadeOut(8); screen.draw(); screen.fadeIn(4); events.updateGameCounter(); events.wait(60, true); + return true; } -void showDarkSideIntro(XeenEngine &vm) { +bool showDarkSideIntro(XeenEngine &vm) { EventsManager &events = *vm._events; Screen &screen = *vm._screen; SoundManager &sound = *vm._sound; + const int XLIST1[] = { + 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 58, 60, 62 + }; + const int YLIST1[] = { + 0, 5, 10, 15, 20, 25, 30, 35, 40, 40, 39, 37, 35, 33, 31 + }; + const int XLIST2[] = { + 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 98, 90, 82 + }; screen.fadeOut(8); screen.loadBackground("pyramid2.raw"); @@ -171,38 +164,42 @@ void showDarkSideIntro(XeenEngine &vm) { screen.loadPage(0); screen.loadPage(1); + // Show Might and Magic Darkside of Xeen title, and gradualy scroll + // the background vertically down to show the Pharoah's base int yp = 0; - int frame = 0; + int frameNum = 0; int idx1 = 0; bool skipElapsed = false; uint32 timeExpired = 0; - // bool fadeFlag = true; + bool fadeFlag = true; - for (int idx = 200; idx > 0; ) { + for (int yCtr = SCREEN_HEIGHT; yCtr > 0; ) { events.updateGameCounter(); screen.vertMerge(yp); sprites[0].draw(screen, 0); - if (frame) - sprites[0].draw(screen, frame); + if (frameNum) + sprites[0].draw(screen, frameNum); idx1 = (idx1 + 1) % 4; if (!idx1) - frame = (frame + 1) % 10; + frameNum = (frameNum + 1) % 10; screen.draw(); if (!skipElapsed) { - timeExpired = MAX(events.timeElapsed(), (uint32)1); + timeExpired = MAX((int)events.timeElapsed() - 1, 1); skipElapsed = true; } - idx -= timeExpired; - frame = MIN(frame + timeExpired, (uint)200); + yCtr -= timeExpired; + yp = MIN(yp + timeExpired, (uint)200); - while (events.timeElapsed() < 1) { - events.pollEventsAndWait(); - if (events.isKeyMousePressed()) - return; + if (events.wait(1, true)) + return false; + + if (fadeFlag) { + screen.fadeIn(4); + fadeFlag = false; } } @@ -214,9 +211,24 @@ void showDarkSideIntro(XeenEngine &vm) { events.updateGameCounter(); events.wait(30, true); + // Zoom into the Pharoah's base closeup view + for (int idx = 14; idx >= 0; --idx) { + events.updateGameCounter(); + sprites[1].draw(screen, 0, Common::Point(XLIST1[idx], YLIST1[idx])); + sprites[1].draw(screen, 1, Common::Point(XLIST2[idx], YLIST1[idx])); + screen.draw(); + + if (idx == 2) + sound.stopMusic(48); + if (events.wait(2, true)) + return false; + } + // TODO: More sound.playSong(voc[0]); sound.playSong(voc[1]); + + return true; } } // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/darkside_intro.h b/engines/xeen/worldofxeen/darkside_intro.h index 535ee21b39..e37f095347 100644 --- a/engines/xeen/worldofxeen/darkside_intro.h +++ b/engines/xeen/worldofxeen/darkside_intro.h @@ -27,9 +27,9 @@ namespace Xeen { -void showDarkSideTitle(XeenEngine &vm); +bool showDarkSideTitle(XeenEngine &vm); -void showDarkSideIntro(XeenEngine &vm); +bool showDarkSideIntro(XeenEngine &vm); } // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp index 125f9f26c6..f7c9336c64 100644 --- a/engines/xeen/worldofxeen/worldofxeen_game.cpp +++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp @@ -28,6 +28,7 @@ namespace Xeen { WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) : XeenEngine(syst, gameDesc) { + _seenDarkSideIntro = false; } void WorldOfXeenEngine::showIntro() { @@ -35,7 +36,9 @@ void WorldOfXeenEngine::showIntro() { if (gDebugLevel == 0) return; - showDarkSideTitle(*this); + bool completed = showDarkSideTitle(*this); + if (!_seenDarkSideIntro && completed) + showDarkSideIntro(*this); } } // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/worldofxeen_game.h b/engines/xeen/worldofxeen/worldofxeen_game.h index f81f566d88..97a8754470 100644 --- a/engines/xeen/worldofxeen/worldofxeen_game.h +++ b/engines/xeen/worldofxeen/worldofxeen_game.h @@ -35,6 +35,8 @@ namespace Xeen { class WorldOfXeenEngine: public XeenEngine { protected: virtual void showIntro(); +public: + bool _seenDarkSideIntro; public: WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); virtual ~WorldOfXeenEngine() {} -- cgit v1.2.3 From d8c28d15ae553d047b7e571f98727fa79ee143f3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 29 Nov 2015 23:34:34 -0500 Subject: XEEN: Create stub files for other Clouds/DarkSide cutscenes --- engines/xeen/module.mk | 3 +++ engines/xeen/worldofxeen/clouds_ending.cpp | 36 ++++++++++++++++++++++++++++ engines/xeen/worldofxeen/clouds_ending.h | 34 ++++++++++++++++++++++++++ engines/xeen/worldofxeen/clouds_intro.cpp | 36 ++++++++++++++++++++++++++++ engines/xeen/worldofxeen/clouds_intro.h | 36 ++++++++++++++++++++++++++++ engines/xeen/worldofxeen/darkside_ending.cpp | 32 +++++++++++++++++++++++++ engines/xeen/worldofxeen/darkside_ending.h | 34 ++++++++++++++++++++++++++ engines/xeen/worldofxeen/darkside_intro.cpp | 2 +- 8 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 engines/xeen/worldofxeen/clouds_ending.cpp create mode 100644 engines/xeen/worldofxeen/clouds_ending.h create mode 100644 engines/xeen/worldofxeen/clouds_intro.cpp create mode 100644 engines/xeen/worldofxeen/clouds_intro.h create mode 100644 engines/xeen/worldofxeen/darkside_ending.cpp create mode 100644 engines/xeen/worldofxeen/darkside_ending.h (limited to 'engines/xeen') diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index a1e62e149f..58a2f1a29a 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -1,6 +1,9 @@ MODULE := engines/xeen MODULE_OBJS := \ + worldofxeen/clouds_ending.o \ + worldofxeen/clouds_intro.o \ + worldofxeen/darkside_ending.o \ worldofxeen/darkside_intro.o \ worldofxeen/worldofxeen_game.o \ character.o \ diff --git a/engines/xeen/worldofxeen/clouds_ending.cpp b/engines/xeen/worldofxeen/clouds_ending.cpp new file mode 100644 index 0000000000..75c8755bb7 --- /dev/null +++ b/engines/xeen/worldofxeen/clouds_ending.cpp @@ -0,0 +1,36 @@ +/* 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 "xeen/worldofxeen/clouds_ending.h" +#include "xeen/sound.h" + +namespace Xeen { + +bool showCloudsEnding(XeenEngine &vm) { + EventsManager &events = *vm._events; + Screen &screen = *vm._screen; + SoundManager &sound = *vm._sound; + + return true; +} + +} // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/clouds_ending.h b/engines/xeen/worldofxeen/clouds_ending.h new file mode 100644 index 0000000000..fc7945f2a1 --- /dev/null +++ b/engines/xeen/worldofxeen/clouds_ending.h @@ -0,0 +1,34 @@ +/* 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 XEEN_CLOUDS_ENDING_H +#define XEEN_CLOUDS_ENDING_H + +#include "xeen/xeen.h" + +namespace Xeen { + +bool showCloudsEnding(XeenEngine &vm); + +} // End of namespace Xeen + +#endif /* XEEN_CLOUDS_ENDING_H */ diff --git a/engines/xeen/worldofxeen/clouds_intro.cpp b/engines/xeen/worldofxeen/clouds_intro.cpp new file mode 100644 index 0000000000..1ea6765761 --- /dev/null +++ b/engines/xeen/worldofxeen/clouds_intro.cpp @@ -0,0 +1,36 @@ +/* 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 "xeen/worldofxeen/clouds_intro.h" +#include "xeen/sound.h" + +namespace Xeen { + +bool showCloudsTitle(XeenEngine &vm) { + return true; +} + +bool showCloudsIntro(XeenEngine &vm) { + return true; +} + +} // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/clouds_intro.h b/engines/xeen/worldofxeen/clouds_intro.h new file mode 100644 index 0000000000..0bd5633315 --- /dev/null +++ b/engines/xeen/worldofxeen/clouds_intro.h @@ -0,0 +1,36 @@ +/* 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 XEEN_CLOUDS_INTRO_H +#define XEEN_CLOUDS_INTRO_H + +#include "xeen/xeen.h" + +namespace Xeen { + +bool showCloudsTitle(XeenEngine &vm); + +bool showCloudsIntro(XeenEngine &vm); + +} // End of namespace Xeen + +#endif /* XEEN_CLOUDS_INTRO_H */ diff --git a/engines/xeen/worldofxeen/darkside_ending.cpp b/engines/xeen/worldofxeen/darkside_ending.cpp new file mode 100644 index 0000000000..0a8211f55c --- /dev/null +++ b/engines/xeen/worldofxeen/darkside_ending.cpp @@ -0,0 +1,32 @@ +/* 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 "xeen/worldofxeen/darkside_ending.h" +#include "xeen/sound.h" + +namespace Xeen { + +bool showDarkSideEnding(XeenEngine &vm) { + return true; +} + +} // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/darkside_ending.h b/engines/xeen/worldofxeen/darkside_ending.h new file mode 100644 index 0000000000..49dcf2d40b --- /dev/null +++ b/engines/xeen/worldofxeen/darkside_ending.h @@ -0,0 +1,34 @@ +/* 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 XEEN_DARKSIDE_ENDING_H +#define XEEN_DARKSIDE_ENDING_H + +#include "xeen/xeen.h" + +namespace Xeen { + +bool showDarkSideEnding(XeenEngine &vm); + +} // End of namespace Xeen + +#endif /* XEEN_DARKSIDE_ENDING_H */ diff --git a/engines/xeen/worldofxeen/darkside_intro.cpp b/engines/xeen/worldofxeen/darkside_intro.cpp index 8148e249d0..7ea03286d3 100644 --- a/engines/xeen/worldofxeen/darkside_intro.cpp +++ b/engines/xeen/worldofxeen/darkside_intro.cpp @@ -20,7 +20,7 @@ * */ -#include "xeen/worldofxeen/worldofxeen_game.h" +#include "xeen/worldofxeen/darkside_intro.h" #include "xeen/sound.h" namespace Xeen { -- cgit v1.2.3 From 873d555add9aaf5eb0d021518f5134142e2c2ff6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 26 Jul 2016 19:54:17 -0400 Subject: XEEN: Add detection for German World of Xeen --- engines/xeen/detection_tables.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'engines/xeen') diff --git a/engines/xeen/detection_tables.h b/engines/xeen/detection_tables.h index 0735daa507..03290b96d8 100644 --- a/engines/xeen/detection_tables.h +++ b/engines/xeen/detection_tables.h @@ -42,6 +42,25 @@ static const XeenGameDescription gameDescriptions[] = { 0 }, + { + // World of Xeen (German) + { + "worldofxeen", + nullptr, + { + {"xeen.cc", 0, "f4e4b3ddc43bd102dbe1637f480f1fa1", 13214150}, + {"dark.cc", 0, "84a86bbbc5f2fe96c0b0325485ed8203", 11173657}, + AD_LISTEND + }, + Common::DE_DEU, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE), + }, + GType_WorldOfXeen, + 0 + }, + { AD_TABLE_END_MARKER, 0, 0 } }; -- cgit v1.2.3 From 552f0cce8e5af656568b4cac2a2fd665f2e8809d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 27 Aug 2016 15:19:25 -0400 Subject: XEEN: Move game cutscene methods into their own classes --- engines/xeen/detection.cpp | 2 +- engines/xeen/module.mk | 8 +- engines/xeen/worldofxeen/clouds_cutscenes.cpp | 43 +++++ engines/xeen/worldofxeen/clouds_cutscenes.h | 55 ++++++ engines/xeen/worldofxeen/clouds_ending.cpp | 36 ---- engines/xeen/worldofxeen/clouds_ending.h | 34 ---- engines/xeen/worldofxeen/clouds_intro.cpp | 36 ---- engines/xeen/worldofxeen/clouds_intro.h | 36 ---- engines/xeen/worldofxeen/darkside_cutscenes.cpp | 241 ++++++++++++++++++++++++ engines/xeen/worldofxeen/darkside_cutscenes.h | 54 ++++++ engines/xeen/worldofxeen/darkside_ending.cpp | 32 ---- engines/xeen/worldofxeen/darkside_ending.h | 34 ---- engines/xeen/worldofxeen/darkside_intro.cpp | 234 ----------------------- engines/xeen/worldofxeen/darkside_intro.h | 36 ---- engines/xeen/worldofxeen/worldofxeen.cpp | 46 +++++ engines/xeen/worldofxeen/worldofxeen.h | 50 +++++ engines/xeen/worldofxeen/worldofxeen_game.cpp | 44 ----- engines/xeen/worldofxeen/worldofxeen_game.h | 47 ----- 18 files changed, 493 insertions(+), 575 deletions(-) create mode 100644 engines/xeen/worldofxeen/clouds_cutscenes.cpp create mode 100644 engines/xeen/worldofxeen/clouds_cutscenes.h delete mode 100644 engines/xeen/worldofxeen/clouds_ending.cpp delete mode 100644 engines/xeen/worldofxeen/clouds_ending.h delete mode 100644 engines/xeen/worldofxeen/clouds_intro.cpp delete mode 100644 engines/xeen/worldofxeen/clouds_intro.h create mode 100644 engines/xeen/worldofxeen/darkside_cutscenes.cpp create mode 100644 engines/xeen/worldofxeen/darkside_cutscenes.h delete mode 100644 engines/xeen/worldofxeen/darkside_ending.cpp delete mode 100644 engines/xeen/worldofxeen/darkside_ending.h delete mode 100644 engines/xeen/worldofxeen/darkside_intro.cpp delete mode 100644 engines/xeen/worldofxeen/darkside_intro.h create mode 100644 engines/xeen/worldofxeen/worldofxeen.cpp create mode 100644 engines/xeen/worldofxeen/worldofxeen.h delete mode 100644 engines/xeen/worldofxeen/worldofxeen_game.cpp delete mode 100644 engines/xeen/worldofxeen/worldofxeen_game.h (limited to 'engines/xeen') diff --git a/engines/xeen/detection.cpp b/engines/xeen/detection.cpp index 64b28bf687..e5b137c394 100644 --- a/engines/xeen/detection.cpp +++ b/engines/xeen/detection.cpp @@ -21,7 +21,7 @@ */ #include "xeen/xeen.h" -#include "xeen/worldofxeen/worldofxeen_game.h" +#include "xeen/worldofxeen/worldofxeen.h" #include "base/plugins.h" #include "common/savefile.h" diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index 58a2f1a29a..de4df4a90f 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -1,11 +1,9 @@ MODULE := engines/xeen MODULE_OBJS := \ - worldofxeen/clouds_ending.o \ - worldofxeen/clouds_intro.o \ - worldofxeen/darkside_ending.o \ - worldofxeen/darkside_intro.o \ - worldofxeen/worldofxeen_game.o \ + worldofxeen/clouds_cutscenes.o \ + worldofxeen/darkside_cutscenes.o \ + worldofxeen/worldofxeen.o \ character.o \ combat.o \ debugger.o \ diff --git a/engines/xeen/worldofxeen/clouds_cutscenes.cpp b/engines/xeen/worldofxeen/clouds_cutscenes.cpp new file mode 100644 index 0000000000..1d578bdbea --- /dev/null +++ b/engines/xeen/worldofxeen/clouds_cutscenes.cpp @@ -0,0 +1,43 @@ +/* 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 "xeen/worldofxeen/clouds_cutscenes.h" +#include "xeen/sound.h" + +namespace Xeen { + +bool CloudsCutscenes::showCloudsTitle() { + // TODO + return true; +} + +bool CloudsCutscenes::showCloudsIntro() { + // TODO + return true; +} + +bool CloudsCutscenes::showCloudsEnding() { + // TODO + return true; +} + +} // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/clouds_cutscenes.h b/engines/xeen/worldofxeen/clouds_cutscenes.h new file mode 100644 index 0000000000..2c2ed602ea --- /dev/null +++ b/engines/xeen/worldofxeen/clouds_cutscenes.h @@ -0,0 +1,55 @@ +/* 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 XEEN_WORLDOFXEEN_CLOUDS_CUTSCENES_H +#define XEEN_WORLDOFXEEN_CLOUDS_CUTSCENES_H + +#include "xeen/xeen.h" + +namespace Xeen { + +class XeenEngine; + +class CloudsCutscenes { +private: + XeenEngine *_vm; +public: + CloudsCutscenes(XeenEngine *vm) : _vm(vm) {} + + /** + * Shows the Clouds of Xeen title screen + */ + bool showCloudsTitle(); + + /** + * Shows the Clouds of Xeen intro sequence + */ + bool showCloudsIntro(); + + /** + * Shows the Clouds of Xeen ending sequence + */ + bool showCloudsEnding(); +}; +} // End of namespace Xeen + +#endif /* XEEN_WORLDOFXEEN_CLOUDS_CUTSCENES_H */ diff --git a/engines/xeen/worldofxeen/clouds_ending.cpp b/engines/xeen/worldofxeen/clouds_ending.cpp deleted file mode 100644 index 75c8755bb7..0000000000 --- a/engines/xeen/worldofxeen/clouds_ending.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* 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 "xeen/worldofxeen/clouds_ending.h" -#include "xeen/sound.h" - -namespace Xeen { - -bool showCloudsEnding(XeenEngine &vm) { - EventsManager &events = *vm._events; - Screen &screen = *vm._screen; - SoundManager &sound = *vm._sound; - - return true; -} - -} // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/clouds_ending.h b/engines/xeen/worldofxeen/clouds_ending.h deleted file mode 100644 index fc7945f2a1..0000000000 --- a/engines/xeen/worldofxeen/clouds_ending.h +++ /dev/null @@ -1,34 +0,0 @@ -/* 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 XEEN_CLOUDS_ENDING_H -#define XEEN_CLOUDS_ENDING_H - -#include "xeen/xeen.h" - -namespace Xeen { - -bool showCloudsEnding(XeenEngine &vm); - -} // End of namespace Xeen - -#endif /* XEEN_CLOUDS_ENDING_H */ diff --git a/engines/xeen/worldofxeen/clouds_intro.cpp b/engines/xeen/worldofxeen/clouds_intro.cpp deleted file mode 100644 index 1ea6765761..0000000000 --- a/engines/xeen/worldofxeen/clouds_intro.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* 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 "xeen/worldofxeen/clouds_intro.h" -#include "xeen/sound.h" - -namespace Xeen { - -bool showCloudsTitle(XeenEngine &vm) { - return true; -} - -bool showCloudsIntro(XeenEngine &vm) { - return true; -} - -} // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/clouds_intro.h b/engines/xeen/worldofxeen/clouds_intro.h deleted file mode 100644 index 0bd5633315..0000000000 --- a/engines/xeen/worldofxeen/clouds_intro.h +++ /dev/null @@ -1,36 +0,0 @@ -/* 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 XEEN_CLOUDS_INTRO_H -#define XEEN_CLOUDS_INTRO_H - -#include "xeen/xeen.h" - -namespace Xeen { - -bool showCloudsTitle(XeenEngine &vm); - -bool showCloudsIntro(XeenEngine &vm); - -} // End of namespace Xeen - -#endif /* XEEN_CLOUDS_INTRO_H */ diff --git a/engines/xeen/worldofxeen/darkside_cutscenes.cpp b/engines/xeen/worldofxeen/darkside_cutscenes.cpp new file mode 100644 index 0000000000..90efef1a96 --- /dev/null +++ b/engines/xeen/worldofxeen/darkside_cutscenes.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 "xeen/worldofxeen/darkside_cutscenes.h" +#include "xeen/worldofxeen/worldofxeen.h" +#include "xeen/sound.h" +#include "xeen/xeen.h" + +namespace Xeen { + +bool DarkSideCutscenes::showDarkSideTitle() { + EventsManager &events = *_vm->_events; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + + // TODO: Starting method, and sound + //sub_28F40 + screen.loadPalette("dark.pal"); + SpriteResource nwc[4] = { + SpriteResource("nwc1.int"), SpriteResource("nwc2.int"), + SpriteResource("nwc3.int"), SpriteResource("nwc4.int") + }; + VOC voc[3]; + voc[0].open("dragon1.voc"); + voc[1].open("dragon2.voc"); + voc[2].open("dragon3.voc"); + + // Load backgrounds + screen.loadBackground("nwc1.raw"); + screen.loadPage(0); + screen.loadBackground("nwc2.raw"); + screen.loadPage(1); + + // Draw the screen and fade it in + screen.horizMerge(0); + screen.draw(); + screen.fadeIn(4); + + // Initial loop for dragon roaring + int nwcIndex = 0, nwcFrame = 0; + for (int idx = 0; idx < 55 && !_vm->shouldQuit(); ++idx) { + // Render the next frame + events.updateGameCounter(); + screen.vertMerge(0); + nwc[nwcIndex].draw(screen, nwcFrame); + screen.draw(); + + switch (idx) { + case 17: + sound.playSound(voc[0]); + break; + case 34: + case 44: + ++nwcIndex; + nwcFrame = 0; + break; + case 35: + sound.playSound(voc[1]); + break; + default: + ++nwcFrame; + } + + if (events.wait(2, true)) + return false; + } + + // Loop for dragon using flyspray + for (int idx = 0; idx < 42 && !_vm->shouldQuit(); ++idx) { + events.updateGameCounter(); + screen.vertMerge(SCREEN_HEIGHT); + nwc[3].draw(screen, idx); + screen.draw(); + + switch (idx) { + case 3: + sound.startMusic(40); + break; + case 11: + sound.startMusic(0); + case 27: + case 30: + sound.startMusic(3); + break; + case 31: + sound.proc2(voc[2]); + break; + case 33: + sound.startMusic(2); + break; + default: + break; + } + + if (events.wait(2, true)) + return false; + } + + // Pause for a bit + if (events.wait(10, true)) + return false; + + voc[0].stop(); + voc[1].stop(); + voc[2].stop(); + sound.stopMusic(95); + + screen.loadBackground("jvc.raw"); + screen.fadeOut(8); + screen.draw(); + screen.fadeIn(4); + + events.updateGameCounter(); + events.wait(60, true); + return true; +} + +bool DarkSideCutscenes::showDarkSideIntro() { + EventsManager &events = *_vm->_events; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + const int XLIST1[] = { + 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 58, 60, 62 + }; + const int YLIST1[] = { + 0, 5, 10, 15, 20, 25, 30, 35, 40, 40, 39, 37, 35, 33, 31 + }; + const int XLIST2[] = { + 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 98, 90, 82 + }; + + screen.fadeOut(8); + screen.loadBackground("pyramid2.raw"); + screen.loadPage(0); + screen.loadPage(1); + screen.loadBackground("pyramid3.raw"); + screen.saveBackground(1); + + SpriteResource sprites[3] = { + SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int") + }; + Common::File voc[2]; + voc[0].open("pharoh1a.voc"); + voc[1].open("pharoh1b.voc"); + + screen.vertMerge(SCREEN_HEIGHT); + screen.loadPage(0); + screen.loadPage(1); + + // Show Might and Magic Darkside of Xeen title, and gradualy scroll + // the background vertically down to show the Pharoah's base + int yp = 0; + int frameNum = 0; + int idx1 = 0; + bool skipElapsed = false; + uint32 timeExpired = 0; + bool fadeFlag = true; + + for (int yCtr = SCREEN_HEIGHT; yCtr > 0; ) { + events.updateGameCounter(); + screen.vertMerge(yp); + + sprites[0].draw(screen, 0); + if (frameNum) + sprites[0].draw(screen, frameNum); + + idx1 = (idx1 + 1) % 4; + if (!idx1) + frameNum = (frameNum + 1) % 10; + + screen.draw(); + if (!skipElapsed) { + timeExpired = MAX((int)events.timeElapsed() - 1, 1); + skipElapsed = true; + } + + yCtr -= timeExpired; + yp = MIN(yp + timeExpired, (uint)200); + + if (events.wait(1, true)) + return false; + + if (fadeFlag) { + screen.fadeIn(4); + fadeFlag = false; + } + } + + screen.vertMerge(SCREEN_HEIGHT); + screen.saveBackground(1); + screen.draw(); + screen.freePages(); + + events.updateGameCounter(); + events.wait(30, true); + + // Zoom into the Pharoah's base closeup view + for (int idx = 14; idx >= 0; --idx) { + events.updateGameCounter(); + sprites[1].draw(screen, 0, Common::Point(XLIST1[idx], YLIST1[idx])); + sprites[1].draw(screen, 1, Common::Point(XLIST2[idx], YLIST1[idx])); + screen.draw(); + + if (idx == 2) + sound.stopMusic(48); + if (events.wait(2, true)) + return false; + } + + // TODO: More + sound.playSong(voc[0]); + sound.playSong(voc[1]); + + return true; +} + +bool DarkSideCutscenes::showDarkSideEnding() { + // TODO + return true; +} + +} // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/darkside_cutscenes.h b/engines/xeen/worldofxeen/darkside_cutscenes.h new file mode 100644 index 0000000000..1b78e3ea2d --- /dev/null +++ b/engines/xeen/worldofxeen/darkside_cutscenes.h @@ -0,0 +1,54 @@ +/* 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 XEEN_WORLDOFXEEN_DARKSIDE_CUTSCENES_H +#define XEEN_WORLDOFXEEN_DARKSIDE_CUTSCENES_H + +namespace Xeen { + +class XeenEngine; + +class DarkSideCutscenes { +private: + XeenEngine *_vm; +public: + DarkSideCutscenes(XeenEngine *vm) : _vm(vm) {} + + /** + * Shows the Dark Side of Xeen title screen + */ + bool showDarkSideTitle(); + + /** + * Shows the Dark Side of Xeen intro sequence + */ + bool showDarkSideIntro(); + + /** + * Shows the Dark Side of Xeen ending sequence + */ + bool showDarkSideEnding(); +}; + +} // End of namespace Xeen + +#endif /* XEEN_WORLDOFXEEN_DARKSIDE_CUTSCENES_H */ diff --git a/engines/xeen/worldofxeen/darkside_ending.cpp b/engines/xeen/worldofxeen/darkside_ending.cpp deleted file mode 100644 index 0a8211f55c..0000000000 --- a/engines/xeen/worldofxeen/darkside_ending.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* 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 "xeen/worldofxeen/darkside_ending.h" -#include "xeen/sound.h" - -namespace Xeen { - -bool showDarkSideEnding(XeenEngine &vm) { - return true; -} - -} // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/darkside_ending.h b/engines/xeen/worldofxeen/darkside_ending.h deleted file mode 100644 index 49dcf2d40b..0000000000 --- a/engines/xeen/worldofxeen/darkside_ending.h +++ /dev/null @@ -1,34 +0,0 @@ -/* 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 XEEN_DARKSIDE_ENDING_H -#define XEEN_DARKSIDE_ENDING_H - -#include "xeen/xeen.h" - -namespace Xeen { - -bool showDarkSideEnding(XeenEngine &vm); - -} // End of namespace Xeen - -#endif /* XEEN_DARKSIDE_ENDING_H */ diff --git a/engines/xeen/worldofxeen/darkside_intro.cpp b/engines/xeen/worldofxeen/darkside_intro.cpp deleted file mode 100644 index 7ea03286d3..0000000000 --- a/engines/xeen/worldofxeen/darkside_intro.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/* 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 "xeen/worldofxeen/darkside_intro.h" -#include "xeen/sound.h" - -namespace Xeen { - -bool showDarkSideTitle(XeenEngine &vm) { - EventsManager &events = *vm._events; - Screen &screen = *vm._screen; - SoundManager &sound = *vm._sound; - - // TODO: Starting method, and sound - //sub_28F40 - screen.loadPalette("dark.pal"); - SpriteResource nwc[4] = { - SpriteResource("nwc1.int"), SpriteResource("nwc2.int"), - SpriteResource("nwc3.int"), SpriteResource("nwc4.int") - }; - VOC voc[3]; - voc[0].open("dragon1.voc"); - voc[1].open("dragon2.voc"); - voc[2].open("dragon3.voc"); - - // Load backgrounds - screen.loadBackground("nwc1.raw"); - screen.loadPage(0); - screen.loadBackground("nwc2.raw"); - screen.loadPage(1); - - // Draw the screen and fade it in - screen.horizMerge(0); - screen.draw(); - screen.fadeIn(4); - - // Initial loop for dragon roaring - int nwcIndex = 0, nwcFrame = 0; - for (int idx = 0; idx < 55 && !vm.shouldQuit(); ++idx) { - // Render the next frame - events.updateGameCounter(); - screen.vertMerge(0); - nwc[nwcIndex].draw(screen, nwcFrame); - screen.draw(); - - switch (idx) { - case 17: - sound.playSound(voc[0]); - break; - case 34: - case 44: - ++nwcIndex; - nwcFrame = 0; - break; - case 35: - sound.playSound(voc[1]); - break; - default: - ++nwcFrame; - } - - if (events.wait(2, true)) - return false; - } - - // Loop for dragon using flyspray - for (int idx = 0; idx < 42 && !vm.shouldQuit(); ++idx) { - events.updateGameCounter(); - screen.vertMerge(SCREEN_HEIGHT); - nwc[3].draw(screen, idx); - screen.draw(); - - switch (idx) { - case 3: - sound.startMusic(40); - break; - case 11: - sound.startMusic(0); - case 27: - case 30: - sound.startMusic(3); - break; - case 31: - sound.proc2(voc[2]); - break; - case 33: - sound.startMusic(2); - break; - default: - break; - } - - if (events.wait(2, true)) - return false; - } - - // Pause for a bit - if (events.wait(10, true)) - return false; - - voc[0].stop(); - voc[1].stop(); - voc[2].stop(); - sound.stopMusic(95); - - screen.loadBackground("jvc.raw"); - screen.fadeOut(8); - screen.draw(); - screen.fadeIn(4); - - events.updateGameCounter(); - events.wait(60, true); - return true; -} - -bool showDarkSideIntro(XeenEngine &vm) { - EventsManager &events = *vm._events; - Screen &screen = *vm._screen; - SoundManager &sound = *vm._sound; - const int XLIST1[] = { - 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 58, 60, 62 - }; - const int YLIST1[] = { - 0, 5, 10, 15, 20, 25, 30, 35, 40, 40, 39, 37, 35, 33, 31 - }; - const int XLIST2[] = { - 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 98, 90, 82 - }; - - screen.fadeOut(8); - screen.loadBackground("pyramid2.raw"); - screen.loadPage(0); - screen.loadPage(1); - screen.loadBackground("pyramid3.raw"); - screen.saveBackground(1); - - SpriteResource sprites[3] = { - SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int") - }; - Common::File voc[2]; - voc[0].open("pharoh1a.voc"); - voc[1].open("pharoh1b.voc"); - - screen.vertMerge(SCREEN_HEIGHT); - screen.loadPage(0); - screen.loadPage(1); - - // Show Might and Magic Darkside of Xeen title, and gradualy scroll - // the background vertically down to show the Pharoah's base - int yp = 0; - int frameNum = 0; - int idx1 = 0; - bool skipElapsed = false; - uint32 timeExpired = 0; - bool fadeFlag = true; - - for (int yCtr = SCREEN_HEIGHT; yCtr > 0; ) { - events.updateGameCounter(); - screen.vertMerge(yp); - - sprites[0].draw(screen, 0); - if (frameNum) - sprites[0].draw(screen, frameNum); - - idx1 = (idx1 + 1) % 4; - if (!idx1) - frameNum = (frameNum + 1) % 10; - - screen.draw(); - if (!skipElapsed) { - timeExpired = MAX((int)events.timeElapsed() - 1, 1); - skipElapsed = true; - } - - yCtr -= timeExpired; - yp = MIN(yp + timeExpired, (uint)200); - - if (events.wait(1, true)) - return false; - - if (fadeFlag) { - screen.fadeIn(4); - fadeFlag = false; - } - } - - screen.vertMerge(SCREEN_HEIGHT); - screen.saveBackground(1); - screen.draw(); - screen.freePages(); - - events.updateGameCounter(); - events.wait(30, true); - - // Zoom into the Pharoah's base closeup view - for (int idx = 14; idx >= 0; --idx) { - events.updateGameCounter(); - sprites[1].draw(screen, 0, Common::Point(XLIST1[idx], YLIST1[idx])); - sprites[1].draw(screen, 1, Common::Point(XLIST2[idx], YLIST1[idx])); - screen.draw(); - - if (idx == 2) - sound.stopMusic(48); - if (events.wait(2, true)) - return false; - } - - // TODO: More - sound.playSong(voc[0]); - sound.playSong(voc[1]); - - return true; -} - -} // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/darkside_intro.h b/engines/xeen/worldofxeen/darkside_intro.h deleted file mode 100644 index e37f095347..0000000000 --- a/engines/xeen/worldofxeen/darkside_intro.h +++ /dev/null @@ -1,36 +0,0 @@ -/* 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 XEEN_DARKSIDE_INTRO_H -#define XEEN_DARKSIDE_INTRO_H - -#include "xeen/xeen.h" - -namespace Xeen { - -bool showDarkSideTitle(XeenEngine &vm); - -bool showDarkSideIntro(XeenEngine &vm); - -} // End of namespace Xeen - -#endif /* XEEN_DARKSIDE_INTRO_H */ diff --git a/engines/xeen/worldofxeen/worldofxeen.cpp b/engines/xeen/worldofxeen/worldofxeen.cpp new file mode 100644 index 0000000000..86a6ee3da7 --- /dev/null +++ b/engines/xeen/worldofxeen/worldofxeen.cpp @@ -0,0 +1,46 @@ +/* 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 "xeen/worldofxeen/worldofxeen.h" +#include "xeen/worldofxeen/darkside_cutscenes.h" +#include "xeen/worldofxeen/clouds_cutscenes.h" +#include "xeen/sound.h" + +namespace Xeen { + +WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) + : XeenEngine(syst, gameDesc), CloudsCutscenes(this), + DarkSideCutscenes(this) { + _seenDarkSideIntro = false; +} + +void WorldOfXeenEngine::showIntro() { + // **DEBUG** + if (gDebugLevel == 0) + return; + + bool completed = showDarkSideTitle(); + if (!_seenDarkSideIntro && completed) + showDarkSideIntro(); +} + +} // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/worldofxeen.h b/engines/xeen/worldofxeen/worldofxeen.h new file mode 100644 index 0000000000..68a83bb89d --- /dev/null +++ b/engines/xeen/worldofxeen/worldofxeen.h @@ -0,0 +1,50 @@ +/* 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 XEEN_WORLDOFXEEN_WORLDOFXEEN_H +#define XEEN_WORLDOFXEEN_WORLDOFXEEN_H + +#include "xeen/xeen.h" +#include "xeen/worldofxeen/clouds_cutscenes.h" +#include "xeen/worldofxeen/darkside_cutscenes.h" + +namespace Xeen { + +/** + * Implements a descendant of the base Xeen engine to handle + * Clouds of Xeen, Dark Side of Xeen, and Worlds of Xeen specific + * game code + */ +class WorldOfXeenEngine: public XeenEngine, public CloudsCutscenes, + public DarkSideCutscenes { +protected: + virtual void showIntro(); +public: + bool _seenDarkSideIntro; +public: + WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); + virtual ~WorldOfXeenEngine() {} +}; + +} // End of namespace Xeen + +#endif /* XEEN_WORLDOFXEEN_WORLDOFXEEN_H */ diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp deleted file mode 100644 index f7c9336c64..0000000000 --- a/engines/xeen/worldofxeen/worldofxeen_game.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* 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 "xeen/worldofxeen/worldofxeen_game.h" -#include "xeen/worldofxeen/darkside_intro.h" -#include "xeen/sound.h" - -namespace Xeen { - -WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) - : XeenEngine(syst, gameDesc) { - _seenDarkSideIntro = false; -} - -void WorldOfXeenEngine::showIntro() { - // **DEBUG** - if (gDebugLevel == 0) - return; - - bool completed = showDarkSideTitle(*this); - if (!_seenDarkSideIntro && completed) - showDarkSideIntro(*this); -} - -} // End of namespace Xeen diff --git a/engines/xeen/worldofxeen/worldofxeen_game.h b/engines/xeen/worldofxeen/worldofxeen_game.h deleted file mode 100644 index 97a8754470..0000000000 --- a/engines/xeen/worldofxeen/worldofxeen_game.h +++ /dev/null @@ -1,47 +0,0 @@ -/* 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 XEEN_WORLDOFXEEN_GAME_H -#define XEEN_WORLDOFXEEN_GAME_H - -#include "xeen/xeen.h" - -namespace Xeen { - -/** - * Implements a descendant of the base Xeen engine to handle - * Clouds of Xeen, Dark Side of Xeen, and Worlds of Xeen specific - * game code - */ -class WorldOfXeenEngine: public XeenEngine { -protected: - virtual void showIntro(); -public: - bool _seenDarkSideIntro; -public: - WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc); - virtual ~WorldOfXeenEngine() {} -}; - -} // End of namespace Xeen - -#endif /* XEEN_WORLDOFXEEN_GAME_H */ -- cgit v1.2.3 From 0c199f079bc1ed62e6c13f292d569fc52eac546c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 27 Aug 2016 16:33:32 -0400 Subject: XEEN: Beginnings of sound effects support --- engines/xeen/dialogs_info.cpp | 2 +- engines/xeen/dialogs_input.cpp | 2 ++ engines/xeen/sound.cpp | 32 +++++++++++++++++++++---- engines/xeen/sound.h | 27 +++++++++++++++++---- engines/xeen/worldofxeen/darkside_cutscenes.cpp | 4 ++-- engines/xeen/xeen.cpp | 3 ++- 6 files changed, 57 insertions(+), 13 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_info.cpp b/engines/xeen/dialogs_info.cpp index 7ccaa7fe71..56755630da 100644 --- a/engines/xeen/dialogs_info.cpp +++ b/engines/xeen/dialogs_info.cpp @@ -81,7 +81,7 @@ void InfoDialog::execute() { void InfoDialog::protectionText() { Party &party = *_vm->_party; - Common::StringArray _lines; +// Common::StringArray _lines; const char *const AA_L024 = "\x3l\n\x9""024"; const char *const AA_R124 = "\x3r\x9""124"; diff --git a/engines/xeen/dialogs_input.cpp b/engines/xeen/dialogs_input.cpp index 8b754ab6de..eec6088a2c 100644 --- a/engines/xeen/dialogs_input.cpp +++ b/engines/xeen/dialogs_input.cpp @@ -263,6 +263,8 @@ int Choose123::execute(int numOptions) { _vm->_mode = oldMode; intf.mainIconsPrint(); + + return result; } void Choose123::loadButtons(int numOptions) { diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp index 00b92472cc..ec8b8c6387 100644 --- a/engines/xeen/sound.cpp +++ b/engines/xeen/sound.cpp @@ -20,27 +20,51 @@ * */ +#include "audio/decoders/voc.h" #include "xeen/sound.h" +#include "xeen/xeen.h" namespace Xeen { +SoundManager *VOC::_sound; + +void VOC::init(XeenEngine *vm) { + _sound = vm->_sound; +} + +void VOC::play() { + _sound->playSound(this, _soundHandle); +} + void VOC::stop() { - warning("TODO: VOC::stop"); + _sound->stopSound(_soundHandle); } -SoundManager::SoundManager(XeenEngine *vm): _vm(vm) { +/*------------------------------------------------------------------------*/ + +SoundManager::SoundManager(XeenEngine *vm, Audio::Mixer *mixer): _vm(vm), _mixer(mixer) { } void SoundManager::proc2(Common::SeekableReadStream &f) { - + // TODO } void SoundManager::startMusic(int v1) { - + // TODO } void SoundManager::stopMusic(int id) { + // TODO } +void SoundManager::playSound(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle) { + Audio::SeekableAudioStream *stream = Audio::makeVOCStream(s, 0); + _mixer->playStream(Audio::Mixer::kPlainSoundType, &soundHandle, stream); + +} + +void SoundManager::stopSound(Audio::SoundHandle &soundHandle) { + _mixer->stopHandle(soundHandle); +} } // End of namespace Xeen diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index 5c123d7d89..172ef9eece 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -23,6 +23,8 @@ #ifndef XEEN_SOUND_H #define XEEN_SOUND_H +#include "audio/mixer.h" +#include "audio/audiostream.h" #include "common/scummsys.h" #include "common/system.h" #include "xeen/files.h" @@ -32,12 +34,18 @@ namespace Xeen { class SoundManager; class VOC: public Common::File { - friend class SoundManager; private: - SoundManager *_sound; + static SoundManager *_sound; + Audio::SoundHandle _soundHandle; public: - VOC() : _sound(nullptr) {} + VOC() {} virtual ~VOC() { stop(); } + static void init(XeenEngine *vm); + + /** + * Start playing the sound + */ + void play(); /** * Stop playing the sound @@ -48,8 +56,9 @@ public: class SoundManager { private: XeenEngine *_vm; + Audio::Mixer *_mixer; public: - SoundManager(XeenEngine *vm); + SoundManager(XeenEngine *vm, Audio::Mixer *mixer); void proc2(Common::SeekableReadStream &f); @@ -61,7 +70,15 @@ public: void playSong(Common::SeekableReadStream &f) {} - void playSound(VOC &voc) {} + /** + * Play a given sound + */ + void playSound(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle); + + /** + * Stop playing a sound + */ + void stopSound(Audio::SoundHandle &soundHandle); void playSample(const Common::SeekableReadStream *stream, int v2 = 1) {} diff --git a/engines/xeen/worldofxeen/darkside_cutscenes.cpp b/engines/xeen/worldofxeen/darkside_cutscenes.cpp index 90efef1a96..6226b52a11 100644 --- a/engines/xeen/worldofxeen/darkside_cutscenes.cpp +++ b/engines/xeen/worldofxeen/darkside_cutscenes.cpp @@ -66,7 +66,7 @@ bool DarkSideCutscenes::showDarkSideTitle() { switch (idx) { case 17: - sound.playSound(voc[0]); + voc[0].play(); break; case 34: case 44: @@ -74,7 +74,7 @@ bool DarkSideCutscenes::showDarkSideTitle() { nwcFrame = 0; break; case 35: - sound.playSound(voc[1]); + voc[1].play(); break; default: ++nwcFrame; diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 90349858ee..3b317f52d6 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -95,9 +95,10 @@ void XeenEngine::initialize() { _screen = new Screen(this); _scripts = new Scripts(this); _screen->setupWindows(); - _sound = new SoundManager(this); + _sound = new SoundManager(this, _mixer); _spells = new Spells(this); _town = new Town(this); + VOC::init(this); File f("029.obj"); _eventData = f.readStream(f.size()); -- cgit v1.2.3 From ef6253fb19822b9a2e9a1ba00418f1d33afff65f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 28 Aug 2016 15:46:10 -0400 Subject: XEEN: gcc compilation fixes --- engines/xeen/character.cpp | 20 ++++++++++++-------- engines/xeen/character.h | 9 ++++++--- engines/xeen/combat.cpp | 13 ++++++++++--- engines/xeen/dialogs_items.cpp | 16 ++++++++-------- engines/xeen/dialogs_party.cpp | 6 +++--- engines/xeen/interface.cpp | 2 +- engines/xeen/party.cpp | 6 +++--- engines/xeen/sound.cpp | 5 +++++ engines/xeen/sound.h | 1 + engines/xeen/sprites.cpp | 2 +- engines/xeen/town.cpp | 9 ++++----- engines/xeen/xsurface.cpp | 4 ++-- engines/xeen/xsurface.h | 2 +- 13 files changed, 57 insertions(+), 38 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index ca224ab4f1..bb7877c69a 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -202,7 +202,7 @@ void InventoryItems::removeItem(int itemIndex) { item._frame = 0; } -XeenEngine *InventoryItems::vm() { +XeenEngine *InventoryItems::getVm() { return Party::_vm; } @@ -297,7 +297,7 @@ void WeaponItems::equipItem(int itemIndex) { */ Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) { XeenItem &i = operator[](itemIndex); - Resources &res = *vm()->_resources; + Resources &res = *getVm()->_resources; return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum, !i._bonusFlags ? res._maeNames[i._material].c_str() : "", @@ -311,7 +311,7 @@ Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) { } void WeaponItems::enchantItem(int itemIndex, int amount) { - SoundManager &sound = *vm()->_sound; + SoundManager &sound = *getVm()->_sound; XeenItem &item = operator[](itemIndex); Character tempCharacter; @@ -463,12 +463,13 @@ void ArmorItems::equipItem(int itemIndex) { */ Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) { XeenItem &i = operator[](itemIndex); - Resources &res = *vm()->_resources; + Resources &res = *getVm()->_resources; return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, !i._bonusFlags ? "" : res._maeNames[i._material].c_str(), (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + displayNum, ARMOR_NAMES[i._id], (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || !i._bonusFlags ? "\b " : "" @@ -476,7 +477,7 @@ Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) { } void ArmorItems::enchantItem(int itemIndex, int amount) { - SoundManager &sound = *vm()->_sound; + SoundManager &sound = *getVm()->_sound; XeenItem &item = operator[](itemIndex); Character tempCharacter; @@ -586,7 +587,7 @@ void AccessoryItems::equipItem(int itemIndex) { */ Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum) { XeenItem &i = operator[](itemIndex); - Resources &res = *vm()->_resources; + Resources &res = *getVm()->_resources; return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, !i._bonusFlags ? "" : res._maeNames[i._material].c_str(), @@ -635,7 +636,7 @@ Common::String AccessoryItems::getAttributes(XeenItem &item, const Common::Strin */ Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) { XeenItem &i = operator[](itemIndex); - Resources &res = *vm()->_resources; + Resources &res = *getVm()->_resources; return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum, !i._bonusFlags ? "" : res._maeNames[i._material].c_str(), @@ -653,7 +654,7 @@ Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) { */ Common::String MiscItems::getAttributes(XeenItem &item, const Common::String &classes) { Common::String specialPower = FIELD_NONE; - Spells &spells = *vm()->_spells; + Spells &spells = *getVm()->_spells; if (item._id) { specialPower = spells._spellNames[MISC_SPELL_INDEX[item._id]]; @@ -1814,6 +1815,9 @@ int Character::makeItem(int p1, int itemIndex, int p3) { newItem._id = miscId; newItem._bonusFlags = miscBonus; break; + + default: + break; } return category; diff --git a/engines/xeen/character.h b/engines/xeen/character.h index f1243f1568..83198a1d8d 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -50,8 +50,7 @@ enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 }; enum CharacterClass { CLASS_KNIGHT = 0, CLASS_PALADIN = 1, CLASS_ARCHER = 2, CLASS_CLERIC = 3, CLASS_SORCERER = 4, CLASS_ROBBER = 5, CLASS_NINJA = 6, CLASS_BARBARIAN = 7, - CLASS_DRUID = 8, CLASS_RANGER = 9, TOTAL_CLASSES = 10, - CLASS_12 = 12, CLASS_15 = 15, CLASS_16 = 16 + CLASS_DRUID = 8, CLASS_RANGER = 9, TOTAL_CLASSES = 10, CLASS_12 = 12, CLASS_15 = 15, CLASS_16 = 16 }; enum Attribute { @@ -114,13 +113,14 @@ protected: ItemCategory _category; const char *const *_names; - XeenEngine *vm(); + XeenEngine *getVm(); void equipError(int itemIndex1, ItemCategory category1, int itemIndex2, ItemCategory category2); virtual Common::String getAttributes(XeenItem &item, const Common::String &classes) = 0; public: InventoryItems(Character *character, ItemCategory category); + virtual ~InventoryItems() {} void clear(); @@ -150,6 +150,7 @@ protected: virtual Common::String getAttributes(XeenItem &item, const Common::String &classes); public: WeaponItems(Character *character) : InventoryItems(character, CATEGORY_WEAPON) {} + virtual ~WeaponItems() {} virtual void equipItem(int itemIndex); @@ -163,6 +164,7 @@ protected: virtual Common::String getAttributes(XeenItem &item, const Common::String &classes); public: ArmorItems(Character *character) : InventoryItems(character, CATEGORY_ARMOR) {} + virtual ~ArmorItems() {} virtual void equipItem(int itemIndex); @@ -187,6 +189,7 @@ protected: virtual Common::String getAttributes(XeenItem &item, const Common::String &classes); public: MiscItems(Character *character) : InventoryItems(character, CATEGORY_MISC) {} + virtual ~MiscItems() {} virtual Common::String getFullDescription(int itemIndex, int displayNum); }; diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 1d03a5128d..13efe912de 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -422,6 +422,9 @@ void Combat::doCharDamage(Character &c, int charNum, int monsterDataIndex) { if (c._currentHp > 0) c._currentHp = 0; break; + + default: + break; } c.subtractHitPoints(damage); @@ -823,7 +826,7 @@ void Combat::doMonsterTurn(int monsterId) { if (cond >= PARALYZED && cond <= ERADICATED) continue; - bool isHated = false; + isHated = false; switch (monsterData._hatesClass) { case CLASS_KNIGHT: case CLASS_PALADIN: @@ -1277,10 +1280,10 @@ void Combat::attack(Character &c, RangeType rangeType) { damage = 0; for (uint charIndex = 0; charIndex < party._activeParty.size(); ++charIndex) { - Character &c = party._activeParty[charIndex]; + Character &ch = party._activeParty[charIndex]; if (_shooting[charIndex] && !_missedShot[charIndex]) { - if (!hitMonster(c, rangeType)) { + if (!hitMonster(ch, rangeType)) { ++_missedShot[charIndex]; } else { damage = _monsterDamage ? _monsterDamage : _weaponDamage; @@ -1337,6 +1340,8 @@ void Combat::attack(Character &c, RangeType rangeType) { case CLASS_SORCERER: divisor = 8; break; + default: + break; } int numberOfAttacks = c.getCurrentLevel() / divisor + 1; @@ -1651,6 +1656,8 @@ bool Combat::hitMonster(Character &c, RangeType rangeType) { case CLASS_SORCERER: divisor = 4; break; + default: + break; } chance += c.getCurrentLevel() / divisor; diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index bdcdffaa84..147f934a61 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -913,8 +913,8 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite break; case ITEMMODE_BLACKSMITH: { - InventoryItems &items = _oldCharacter->_items[category]; - if (items[INV_ITEMS_TOTAL - 1]._id) { + InventoryItems &invItems = _oldCharacter->_items[category]; + if (invItems[INV_ITEMS_TOTAL - 1]._id) { // If the last slot is in use, it means the list is full ErrorScroll::show(_vm, Common::String::format(BACKPACK_IS_FULL, _oldCharacter->_name.c_str())); @@ -1021,13 +1021,13 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite if (Confirm::show(_vm, msg) && party.subtract(0, cost, 0)) { Common::String details = c._items[category].getIdentifiedDetails(itemIndex); Common::String desc = c._items[category].getFullDescription(itemIndex); - Common::String msg = Common::String::format(IDENTIFY_ITEM_MSG, + Common::String str = Common::String::format(IDENTIFY_ITEM_MSG, desc.c_str(), details.c_str()); - Window &w = screen._windows[14]; - w.open(); - w.writeString(msg); - w.update(); + Window &win = screen._windows[14]; + win.open(); + win.writeString(str); + win.update(); saveButtons(); clearButtons(); @@ -1037,7 +1037,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite events.clearEvents(); restoreButtons(); - w.close(); + win.close(); } break; } diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index 544c110c82..69761bb4ec 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -240,8 +240,8 @@ void PartyDialog::execute() { // Rebuild the character list _charList.clear(); for (int idx = 0; idx < XEEN_TOTAL_CHARACTERS; ++idx) { - Character &c = party._roster[idx]; - if (!c._name.empty() && c._savedMazeId == party._priorMazeId) { + Character &ch = party._roster[idx]; + if (!ch._name.empty() && ch._savedMazeId == party._priorMazeId) { _charList.push_back(idx); } } @@ -339,7 +339,7 @@ void PartyDialog::setupFaces(int firstDisplayChar, bool updateFlag) { drawParty(updateFlag); // Set up the sprite set to use for each face - for (int posIndex = 0; posIndex < 4; ++posIndex) { + for (posIndex = 0; posIndex < 4; ++posIndex) { if ((firstDisplayChar + posIndex) >= (int)_charList.size()) _faceDrawStructs[posIndex]._sprites = nullptr; else diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index d1a1478d95..f9f1eebd10 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -1006,7 +1006,7 @@ bool Interface::checkMoveDirection(int key) { break; } } else { - int surfaceId = map.getCell(2); + surfaceId = map.getCell(2); if (surfaceId >= map.mazeData()._difficulties._wallNoPass) { party._mazeDirection = dir; sound.playFX(46); diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 9f56b98c4c..1db4a14f59 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -638,9 +638,9 @@ void Party::giveTreasure() { // Fall back on checking the entire conscious party for (charIndex = 0; charIndex < (int)_activeParty.size(); ++charIndex) { - Character &c = _activeParty[charIndex]; - if (!c._items[(ItemCategory)categoryNum].isFull() && !c.isDisabledOrDead()) { - giveTreasureToCharacter(c, (ItemCategory)categoryNum, itemNum); + Character &ch = _activeParty[charIndex]; + if (!ch._items[(ItemCategory)categoryNum].isFull() && !ch.isDisabledOrDead()) { + giveTreasureToCharacter(ch, (ItemCategory)categoryNum, itemNum); break; } } diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp index ec8b8c6387..c0a49aeb22 100644 --- a/engines/xeen/sound.cpp +++ b/engines/xeen/sound.cpp @@ -28,6 +28,11 @@ namespace Xeen { SoundManager *VOC::_sound; +VOC::VOC(const Common::String &name) { + if (!open(name)) + error("Could not open - %s", name.c_str()); +} + void VOC::init(XeenEngine *vm) { _sound = vm->_sound; } diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index 172ef9eece..bcee6f2f45 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -39,6 +39,7 @@ private: Audio::SoundHandle _soundHandle; public: VOC() {} + VOC(const Common::String &name); virtual ~VOC() { stop(); } static void init(XeenEngine *vm); diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 3491f6fc7b..b29fb2d053 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -185,7 +185,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi destPos.y++; } else { scaleMaskX = scaleMaskXCopy; - int xOffset = f.readByte(); + xOffset = f.readByte(); // Initialize the array to hold the temporary data for the line. We do this to make it simpler // to handle both deciding which pixels to draw in a scaled image, as well as when images diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 9b4bfa3ab1..221f5d9978 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -704,7 +704,7 @@ Character *Town::doTavernOptions(Character *c) { case Common::KEYCODE_s: { // Sign In - int idx = isDarkCc ? (party._mazeId - 29) >> 1 : party._mazeId - 28; + idx = isDarkCc ? (party._mazeId - 29) >> 1 : party._mazeId - 28; assert(idx >= 0); party._mazePosition.x = TAVERN_EXIT_LIST[isDarkCc ? 1 : 0][_townActionId][idx][0]; party._mazePosition.y = TAVERN_EXIT_LIST[isDarkCc ? 1 : 0][_townActionId][idx][1]; @@ -717,7 +717,7 @@ Character *Town::doTavernOptions(Character *c) { party._mazeDirection = DIR_SOUTH; party._priorMazeId = party._mazeId; - for (uint idx = 0; idx < party._activeParty.size(); ++idx) { + for (idx = 0; idx < (int)party._activeParty.size(); ++idx) { party._activeParty[idx]._savedMazeId = party._mazeId; party._activeParty[idx]._xeenSide = map._loadDarkSide; } @@ -825,8 +825,8 @@ Character *Town::doTempleOptions(Character *c) { intf.drawParty(true); sound.playSample(nullptr, 0); - File f("ahh.voc"); - sound.playSample(&f, 1); + VOC voc("ahh.voc"); + voc.play(); _flag1 = true; _donation = 0; } @@ -1030,7 +1030,6 @@ void Town::depositWithdrawl(int choice) { } } - uint gold, gems; if (choice) { gold = party._bankGold; gems = party._bankGems; diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp index 04a264a80c..00d333d6d8 100644 --- a/engines/xeen/xsurface.cpp +++ b/engines/xeen/xsurface.cpp @@ -40,8 +40,8 @@ XSurface::~XSurface() { free(); } -void XSurface::create(uint16 w, uint16 h) { - Graphics::Surface::create(w, h, Graphics::PixelFormat::createFormatCLUT8()); +void XSurface::create(uint16 w_, uint16 h_) { + Graphics::Surface::create(w_, h_, Graphics::PixelFormat::createFormatCLUT8()); _freeFlag = true; } diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h index d8747d4372..299cc51f1d 100644 --- a/engines/xeen/xsurface.h +++ b/engines/xeen/xsurface.h @@ -40,7 +40,7 @@ public: XSurface(int w, int h); virtual ~XSurface(); - void create(uint16 w, uint16 h); + void create(uint16 w_, uint16 h_); void create(XSurface *s, const Common::Rect &bounds); -- cgit v1.2.3 From dffa696b7beea02782579a004862f4aa86e8f3e6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 28 Aug 2016 16:14:38 -0400 Subject: XEEN: gcc compilation fixes --- engines/xeen/character.cpp | 6 ++++++ engines/xeen/combat.cpp | 14 +++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index bb7877c69a..51f288c595 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -303,6 +303,7 @@ Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) { !i._bonusFlags ? res._maeNames[i._material].c_str() : "", (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + displayNum, WEAPON_NAMES[i._id], !i._bonusFlags ? "" : BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK], (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || @@ -593,6 +594,7 @@ Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum) !i._bonusFlags ? "" : res._maeNames[i._material].c_str(), (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + displayNum, ARMOR_NAMES[i._id], (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || !i._bonusFlags ? "\b " : "" @@ -642,6 +644,7 @@ Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) { !i._bonusFlags ? "" : res._maeNames[i._material].c_str(), (i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "", (i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "", + displayNum, ARMOR_NAMES[i._id], (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || !i._id ? "\b " : "" @@ -1722,6 +1725,9 @@ int Character::makeItem(int p1, int itemIndex, int p3) { case CATEGORY_MISC: v8 = 4; break; + + default: + break; } if (p1 != 1 || category == CATEGORY_MISC) { diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 13efe912de..c8cece7b10 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -496,11 +496,12 @@ void Combat::moveMonsters() { if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]], arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0, arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex], - idx)) - if (arrIndex >= 21 && arrIndex <= 27) { - moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0)); - } else { - moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex])); + idx)) { + if (arrIndex >= 21 && arrIndex <= 27) { + moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0)); + } else { + moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex])); + } } } break; @@ -520,6 +521,9 @@ void Combat::moveMonsters() { MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) { moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex])); } + + default: + break; } } } -- cgit v1.2.3 From fd2d4622966d36299129b3f1654484b49ee0c996 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 28 Aug 2016 17:52:56 -0400 Subject: XEEN: Moved method comments from CPP to header files --- engines/xeen/character.cpp | 81 -------------------------------- engines/xeen/character.h | 80 ++++++++++++++++++++++++++++++++ engines/xeen/combat.cpp | 36 --------------- engines/xeen/combat.h | 36 +++++++++++++++ engines/xeen/dialogs.cpp | 10 ---- engines/xeen/dialogs.h | 9 ++++ engines/xeen/dialogs_char_info.cpp | 12 ----- engines/xeen/dialogs_char_info.h | 12 +++++ engines/xeen/dialogs_input.cpp | 6 --- engines/xeen/dialogs_input.h | 6 +++ engines/xeen/dialogs_items.cpp | 18 -------- engines/xeen/dialogs_items.h | 18 ++++++++ engines/xeen/dialogs_party.cpp | 26 ----------- engines/xeen/dialogs_party.h | 26 +++++++++++ engines/xeen/events.cpp | 24 ---------- engines/xeen/events.h | 18 ++++++++ engines/xeen/files.cpp | 16 ------- engines/xeen/files.h | 20 ++++++++ engines/xeen/font.cpp | 30 ------------ engines/xeen/font.h | 30 ++++++++++++ engines/xeen/interface.cpp | 32 +------------ engines/xeen/interface.h | 28 +++++++++++ engines/xeen/interface_map.cpp | 29 ------------ engines/xeen/interface_map.h | 29 ++++++++++++ engines/xeen/map.cpp | 19 -------- engines/xeen/map.h | 19 ++++++++ engines/xeen/module.mk | 1 - engines/xeen/party.cpp | 19 -------- engines/xeen/party.h | 19 ++++++++ engines/xeen/saves.cpp | 6 --- engines/xeen/saves.h | 6 +++ engines/xeen/screen.cpp | 30 ------------ engines/xeen/screen.h | 27 +++++++++++ engines/xeen/scripts.cpp | 74 ----------------------------- engines/xeen/scripts.h | 95 ++++++++++++++++++++++++++++++++++++++ engines/xeen/spells.cpp | 17 ------- engines/xeen/spells.h | 17 +++++++ engines/xeen/sprites.cpp | 18 -------- engines/xeen/sprites.h | 15 ++++++ engines/xeen/town.cpp | 3 -- engines/xeen/town.h | 3 ++ engines/xeen/xeen.cpp | 3 -- engines/xeen/xeen.h | 14 +++--- 43 files changed, 522 insertions(+), 515 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index 51f288c595..2ab532938b 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -78,9 +78,6 @@ void InventoryItems::clear() { operator[](idx).clear(); } -/** -* Return whether a given item passes class-based usage restrictions -*/ bool InventoryItems::passRestrictions(int itemId, bool showError) const { CharacterClass charClass = _character->_class; @@ -117,9 +114,6 @@ bool InventoryItems::passRestrictions(int itemId, bool showError) const { return false; } -/** - * Return the bare name of a given inventory item - */ Common::String InventoryItems::getName(int itemIndex) { int id = operator[](itemIndex)._id; return _names[id]; @@ -143,9 +137,6 @@ Common::String InventoryItems::getIdentifiedDetails(int itemIndex) { return getAttributes(item, classes); } -/** - * Discard an item from the inventory - */ bool InventoryItems::discardItem(int itemIndex) { XeenItem &item = operator[](itemIndex); XeenEngine *vm = Party::_vm; @@ -167,9 +158,6 @@ bool InventoryItems::discardItem(int itemIndex) { return true; } -/** - * Sorts the items list, removing any empty item slots to the end of the array - */ void InventoryItems::sort() { for (uint idx = 0; idx < size(); ++idx) { if (operator[](idx)._id == 0) { @@ -189,9 +177,6 @@ void InventoryItems::sort() { } } -/** - * Un-equips the given item - */ void InventoryItems::removeItem(int itemIndex) { XeenItem &item = operator[](itemIndex); XeenEngine *vm = Party::_vm; @@ -228,19 +213,12 @@ void InventoryItems::enchantItem(int itemIndex, int amount) { ErrorScroll::show(vm, Common::String::format(NOT_ENCHANTABLE, SPELL_FAILED)); } -/** - * Return if the given inventory items list is full - */ bool InventoryItems::isFull() const { return operator[](size() - 1)._id != 0; } - /*------------------------------------------------------------------------*/ -/** - * Equip a given weapon - */ void WeaponItems::equipItem(int itemIndex) { XeenItem &item = operator[](itemIndex); @@ -291,10 +269,6 @@ void WeaponItems::equipItem(int itemIndex) { } } -/** - * Assembles a full lines description for a specified item for use in - * the Items dialog - */ Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) { XeenItem &i = operator[](itemIndex); Resources &res = *getVm()->_resources; @@ -377,9 +351,6 @@ Common::String WeaponItems::getAttributes(XeenItem &item, const Common::String & /*------------------------------------------------------------------------*/ -/** - * Equip a given piece of armor - */ void ArmorItems::equipItem(int itemIndex) { XeenItem &item = operator[](itemIndex); @@ -458,10 +429,6 @@ void ArmorItems::equipItem(int itemIndex) { } } -/** - * Assembles a full lines description for a specified item for use in - * the Items dialog - */ Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) { XeenItem &i = operator[](itemIndex); Resources &res = *getVm()->_resources; @@ -531,9 +498,6 @@ Common::String ArmorItems::getAttributes(XeenItem &item, const Common::String &c /*------------------------------------------------------------------------*/ -/** - * Equip a given accessory - */ void AccessoryItems::equipItem(int itemIndex) { XeenItem &item = operator[](itemIndex); @@ -582,10 +546,6 @@ void AccessoryItems::equipItem(int itemIndex) { } } -/** - * Assembles a full lines description for a specified item for use in - * the Items dialog - */ Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum) { XeenItem &i = operator[](itemIndex); Resources &res = *getVm()->_resources; @@ -632,10 +592,6 @@ Common::String AccessoryItems::getAttributes(XeenItem &item, const Common::Strin /*------------------------------------------------------------------------*/ -/** - * Assembles a full lines description for a specified item for use in - * the Items dialog - */ Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) { XeenItem &i = operator[](itemIndex); Resources &res = *getVm()->_resources; @@ -681,9 +637,6 @@ InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) { return *_itemSets[category]; } -/** - * Breaks all the items in a given character's inventory - */ void InventoryItemsGroup::breakAllItems() { for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { if ((*_itemSets[0])[idx]._id != 34) { @@ -848,9 +801,6 @@ void Character::synchronize(Common::Serializer &s) { s.syncAsByte(_currentCombatSpell); } -/** - * Returns the worst condition the character is suffering from - */ Condition Character::worstCondition() const { for (int cond = ERADICATED; cond >= CURSED; --cond) { if (_conditions[cond]) @@ -860,9 +810,6 @@ Condition Character::worstCondition() const { return NO_CONDITION; } -/** - * Returns whether the given character has a disabling condition, but still alive - */ bool Character::isDisabled() const { Condition condition = worstCondition(); @@ -870,27 +817,18 @@ bool Character::isDisabled() const { || condition == STONED || condition == ERADICATED; } -/** -* Returns whether the given character has a disabling condition, or is dead -*/ bool Character::isDisabledOrDead() const { Condition condition = worstCondition(); return condition == ASLEEP || (condition >= PARALYZED && condition <= ERADICATED); } -/** - * Returns whether the given character has a dead condition - */ bool Character::isDead() const { Condition condition = worstCondition(); return condition >= DEAD && condition <= ERADICATED; } -/** - * Get the character's age - */ int Character::getAge(bool ignoreTemp) const { int year = MIN(Party::_vm->_party->_year - _birthYear, (uint)254); @@ -967,9 +905,6 @@ int Character::getMaxSP() const { return result; } -/** - * Get the effective value of a given stat for the character - */ uint Character::getStat(Attribute attrib, bool baseOnly) const { AttributePair attr; int mode = 0; @@ -1024,10 +959,6 @@ uint Character::getStat(Attribute attrib, bool baseOnly) const { return MAX(attr._permanent, (uint)0); } -/** - * Return the color number to use for a given stat value in the character - * info or quick reference dialogs - */ int Character::statColor(int amount, int threshold) { if (amount < 1) return 6; @@ -1136,9 +1067,6 @@ int Character::getArmorClass(bool baseOnly) const { return MAX(result, 0); } -/** - * Returns the thievery skill level, adjusted by class and race - */ int Character::getThievery() const { int result = getCurrentLevel() * 2; @@ -1258,9 +1186,6 @@ int Character::itemScan(int itemId) const { return result; } -/** - * Modifies a passed attribute value based on player's condition - */ int Character::conditionMod(Attribute attrib) const { if (_conditions[DEAD] || _conditions[STONED] || _conditions[ERADICATED]) return 0; @@ -1829,9 +1754,6 @@ int Character::makeItem(int p1, int itemIndex, int p3) { return category; } -/** - * Add hit points to a character - */ void Character::addHitPoints(int amount) { Interface &intf = *Party::_vm->_interface; Common::fill(&intf._charFX[0], &intf._charFX[MAX_ACTIVE_PARTY], 0); @@ -1852,9 +1774,6 @@ void Character::addHitPoints(int amount) { Common::fill(&intf._charFX[0], &intf._charFX[MAX_ACTIVE_PARTY], 0); } -/** - * Remove hit points fromo the character - */ void Character::subtractHitPoints(int amount) { SoundManager &sound = *Party::_vm->_sound; _currentHp -= amount; diff --git a/engines/xeen/character.h b/engines/xeen/character.h index 83198a1d8d..903d8faabc 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -124,24 +124,42 @@ public: void clear(); + /** + * Return whether a given item passes class-based usage restrictions + */ bool passRestrictions(int itemId, bool showError) const; + /** + * Return the bare name of a given inventory item + */ Common::String getName(int itemIndex); virtual Common::String getFullDescription(int itemIndex, int displayNum = 15) = 0; Common::String getIdentifiedDetails(int itemIndex); + /** + * Discard an item from the inventory + */ bool discardItem(int itemIndex); virtual void equipItem(int itemIndex) {} + /** + * Un-equips the given item + */ void removeItem(int itemIndex); + /** + * Sorts the items list, removing any empty item slots to the end of the array + */ void sort(); virtual void enchantItem(int itemIndex, int amount); + /** + * Return if the given inventory items list is full + */ bool isFull() const; }; @@ -152,8 +170,15 @@ public: WeaponItems(Character *character) : InventoryItems(character, CATEGORY_WEAPON) {} virtual ~WeaponItems() {} + /** + * Equip a given weapon + */ virtual void equipItem(int itemIndex); + /** + * Assembles a full lines description for a specified item for use in + * the Items dialog + */ virtual Common::String getFullDescription(int itemIndex, int displayNum); virtual void enchantItem(int itemIndex, int amount); @@ -166,8 +191,15 @@ public: ArmorItems(Character *character) : InventoryItems(character, CATEGORY_ARMOR) {} virtual ~ArmorItems() {} + /** + * Equip a given piece of armor + */ virtual void equipItem(int itemIndex); + /** + * Assembles a full lines description for a specified item for use in + * the Items dialog + */ virtual Common::String getFullDescription(int itemIndex, int displayNum); virtual void enchantItem(int itemIndex, int amount); @@ -179,8 +211,15 @@ protected: public: AccessoryItems(Character *character) : InventoryItems(character, CATEGORY_ACCESSORY) {} + /** + * Equip a given accessory + */ virtual void equipItem(int itemIndex); + /** + * Assembles a full lines description for a specified item for use in + * the Items dialog + */ virtual Common::String getFullDescription(int itemIndex, int displayNum); }; @@ -191,6 +230,10 @@ public: MiscItems(Character *character) : InventoryItems(character, CATEGORY_MISC) {} virtual ~MiscItems() {} + /** + * Assembles a full lines description for a specified item for use in + * the Items dialog + */ virtual Common::String getFullDescription(int itemIndex, int displayNum); }; @@ -203,6 +246,9 @@ public: InventoryItems &operator[](ItemCategory category); + /** + * Breaks all the items in a given character's inventory + */ void breakAllItems(); }; @@ -218,6 +264,9 @@ public: class Character { private: + /** + * Modifies a passed attribute value based on player's condition + */ int conditionMod(Attribute attrib) const; public: Common::String _name; @@ -275,22 +324,44 @@ public: void synchronize(Common::Serializer &s); + /** + * Returns the worst condition the character is suffering from + */ Condition worstCondition() const; + /** + * Returns whether the given character has a disabling condition, but still alive + */ bool isDisabled() const; + /** + * Returns whether the given character has a disabling condition, or is dead + */ bool isDisabledOrDead() const; + /** + * Returns whether the given character has a dead condition + */ bool isDead() const; + /** + * Get the character's age + */ int getAge(bool ignoreTemp = false) const; int getMaxHP() const; int getMaxSP() const; + /** + * Get the effective value of a given stat for the character + */ uint getStat(Attribute attrib, bool baseOnly = false) const; + /** + * Return the color number to use for a given stat value in the character + * info or quick reference dialogs + */ static int statColor(int amount, int threshold); int statBonus(uint statValue) const; @@ -305,6 +376,9 @@ public: int getArmorClass(bool baseOnly = false) const; + /** + * Returns the thievery skill level, adjusted by class and race + */ int getThievery() const; uint getCurrentLevel() const; @@ -327,8 +401,14 @@ public: int makeItem(int p1, int itemIndex, int p3); + /** + * Add hit points to a character + */ void addHitPoints(int amount); + /** + * Remove hit points fromo the character + */ void subtractHitPoints(int amount); bool hasSpecialItem() const; diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index c8cece7b10..3faff3d157 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -256,9 +256,6 @@ loop: } } -/** - * Do damage to a specific character - */ void Combat::doCharDamage(Character &c, int charNum, int monsterDataIndex) { EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; @@ -664,9 +661,6 @@ void Combat::setupMonsterAttack(int monsterDataIndex, const Common::Point &pt) { } } -/** - * Determines whether a given monster can move - */ bool Combat::monsterCanMove(const Common::Point &pt, int wallShift, int xDiff, int yDiff, int monsterId) { Map &map = *_vm->_map; @@ -709,9 +703,6 @@ bool Combat::monsterCanMove(const Common::Point &pt, int wallShift, } } -/** - * Moves a monster by a given delta amount if it's a valid move - */ void Combat::moveMonster(int monsterId, const Common::Point &moveDelta) { Map &map = *_vm->_map; MazeMonster &monster = map._mobData._monsters[monsterId]; @@ -1062,9 +1053,6 @@ int Combat::stopAttack(const Common::Point &diffPt) { } } -/** - * Setup the combat party with a copy of the currently active party - */ void Combat::setupCombatParty() { Party &party = *_vm->_party; @@ -1123,9 +1111,6 @@ void Combat::setSpeedTable() { } } -/** - * Returns true if all participants in the combat are disabled - */ bool Combat::allHaveGone() const { for (uint idx = 0; idx < _charsGone.size(); ++idx) { if (!_charsGone[idx]) { @@ -1142,9 +1127,6 @@ bool Combat::allHaveGone() const { return true; } -/** - * Returns true if all the characters of the party are disabled - */ bool Combat::charsCantAct() const { for (uint idx = 0; idx < _combatParty.size(); ++idx) { if (!_combatParty[idx]->isDisabledOrDead()) @@ -1154,9 +1136,6 @@ bool Combat::charsCantAct() const { return true; } -/** - * Return a description of the monsters being faced - */ Common::String Combat::getMonsterDescriptions() { Map &map = *_vm->_map; Common::String lines[3]; @@ -1583,16 +1562,10 @@ void Combat::attack2(int damage, RangeType rangeType) { } } -/** - * Flag the currently active character as blocking/defending - */ void Combat::block() { _charsBlocked[_whosTurn] = true; } -/** - * Perform whatever the current combat character's quick action is - */ void Combat::quickFight() { Spells &spells = *_vm->_spells; Character *c = _combatParty[_whosTurn]; @@ -1617,9 +1590,6 @@ void Combat::quickFight() { } } -/** - * Current selected character is trying to run away - */ void Combat::run() { Map &map = *_vm->_map; SoundManager &sound = *_vm->_sound; @@ -1803,9 +1773,6 @@ int Combat::getMonsterResistence(RangeType rangeType) { return damage; } -/** - * Distribute experience between active party members - */ void Combat::giveExperience(int experience) { Party &party = *_vm->_party; bool inCombat = _vm->_mode == MODE_COMBAT; @@ -2089,9 +2056,6 @@ done: party.giveTreasure(); } -/** - * Fires off a ranged attack at all oncoming monsters - */ void Combat::shootRangedWeapon() { _rangeType = RT_ALL; _damageType = DT_PHYSICAL; diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 33309b243b..1a1fc3a41b 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -88,6 +88,9 @@ private: int getMonsterResistence(RangeType rangeType); + /** + * Distribute experience between active party members + */ void giveExperience(int experience); public: Common::Array<Character *> _combatParty; @@ -136,35 +139,65 @@ public: void giveCharDamage(int damage, DamageType attackType, int charIndex); + /** + * Do damage to a specific character + */ void doCharDamage(Character &c, int charNum, int monsterDataIndex); void moveMonsters(); + /** + * Setup the combat party with a copy of the currently active party + */ void setupCombatParty(); void setSpeedTable(); + /** + * Returns true if all participants in the combat are disabled + */ bool allHaveGone() const; + /** + * Returns true if all the characters of the party are disabled + */ bool charsCantAct() const; + /** + * Return a description of the monsters being faced + */ Common::String getMonsterDescriptions(); void attack(Character &c, RangeType rangeType); + /** + * Flag the currently active character as blocking/defending + */ void block(); + /** + * Perform whatever the current combat character's quick action is + */ void quickFight(); + /** + * Current selected character is trying to run away + */ void run(); void monstersAttack(); void setupMonsterAttack(int monsterDataIndex, const Common::Point &pt); + /** + * Determines whether a given monster can move + */ bool monsterCanMove(const Common::Point &pt, int wallShift, int v1, int v2, int monsterId); + /** + * Moves a monster by a given delta amount if it's a valid move + */ void moveMonster(int monsterId, const Common::Point &moveDelta); void doMonsterTurn(int monsterId); @@ -177,6 +210,9 @@ public: void multiAttack(int powNum); + /** + * Fires off a ranged attack at all oncoming monsters + */ void shootRangedWeapon(); }; diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp index 77cdd92169..4ecd1c775c 100644 --- a/engines/xeen/dialogs.cpp +++ b/engines/xeen/dialogs.cpp @@ -29,9 +29,6 @@ namespace Xeen { -/** - * Saves the current list of buttons - */ void ButtonContainer::saveButtons() { _savedButtons.push(_buttons); clearButtons(); @@ -100,10 +97,6 @@ bool ButtonContainer::checkEvents(XeenEngine *vm) { return false; } - -/** -* Draws the scroll in the background -*/ void ButtonContainer::doScroll(XeenEngine *vm, bool drawFlag, bool doFade) { Screen &screen = *vm->_screen; EventsManager &events = *vm->_events; @@ -205,9 +198,6 @@ void ButtonContainer::doScroll(XeenEngine *vm, bool drawFlag, bool doFade) { delete hand[i]; } -/** - * Draws the buttons onto the passed surface - */ void ButtonContainer::drawButtons(XSurface *surface) { for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) { UIButton &btn = _buttons[btnIndex]; diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h index 6e809ba2dc..51eafa5f54 100644 --- a/engines/xeen/dialogs.h +++ b/engines/xeen/dialogs.h @@ -53,12 +53,18 @@ protected: Common::Array<UIButton> _buttons; int _buttonValue; + /** + * Draws the scroll in the background + */ void doScroll(XeenEngine *vm, bool drawFlag, bool doFade); bool checkEvents(XeenEngine *vm); public: ButtonContainer() : _buttonValue(0) {} + /** + * Saves the current list of buttons + */ void saveButtons(); void clearButtons(); @@ -71,6 +77,9 @@ public: void addPartyButtons(XeenEngine *vm); + /** + * Draws the buttons onto the passed surface + */ void drawButtons(XSurface *surface); }; diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp index c00916cd6f..0494c22b9c 100644 --- a/engines/xeen/dialogs_char_info.cpp +++ b/engines/xeen/dialogs_char_info.cpp @@ -213,9 +213,6 @@ exit: _vm->_combat->_itemFlag = false; } -/** - * Load the draw structure list with frame numbers and positions - */ void CharacterInfo::loadDrawStructs() { _drawList[0] = DrawStruct(0, 2, 16); _drawList[1] = DrawStruct(2, 2, 39); @@ -247,9 +244,6 @@ void CharacterInfo::loadDrawStructs() { _drawList[idx]._sprites = &_iconSprites; } -/** - * Set up the button list for the dialog - */ void CharacterInfo::addButtons() { addButton(Common::Rect(10, 24, 34, 44), 1001, &_iconSprites); addButton(Common::Rect(10, 47, 34, 67), 1002, &_iconSprites); @@ -278,9 +272,6 @@ void CharacterInfo::addButtons() { addPartyButtons(_vm); } -/** - * Return a string containing the details of the character - */ Common::String CharacterInfo::loadCharacterDetails(const Character &c) { Condition condition = c.worstCondition(); Party &party = *_vm->_party; @@ -324,9 +315,6 @@ Common::String CharacterInfo::loadCharacterDetails(const Character &c) { ); } -/** - * Cursor display handling - */ void CharacterInfo::showCursor(bool flag) { Screen &screen = *_vm->_screen; const int CURSOR_X[5] = { 9, 60, 111, 176, 0 }; diff --git a/engines/xeen/dialogs_char_info.h b/engines/xeen/dialogs_char_info.h index 5a20ff2248..90b35a9f6b 100644 --- a/engines/xeen/dialogs_char_info.h +++ b/engines/xeen/dialogs_char_info.h @@ -40,12 +40,24 @@ private: void execute(int charIndex); + /** + * Load the draw structure list with frame numbers and positions + */ void loadDrawStructs(); + /** + * Set up the button list for the dialog + */ void addButtons(); + /** + * Return a string containing the details of the character + */ Common::String loadCharacterDetails(const Character &c); + /** + * Cursor display handling + */ void showCursor(bool flag); bool expandStat(int attrib, const Character &c); diff --git a/engines/xeen/dialogs_input.cpp b/engines/xeen/dialogs_input.cpp index eec6088a2c..5833733353 100644 --- a/engines/xeen/dialogs_input.cpp +++ b/engines/xeen/dialogs_input.cpp @@ -35,9 +35,6 @@ int Input::show(XeenEngine *vm, Window *window, Common::String &line, return result; } -/** - * Allows the user to enter a string - */ int Input::getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric) { _vm->_noDirectionSense = true; Common::String msg = Common::String::format("\x3""l\t000\x4%03d\x0""c", maxWidth); @@ -75,9 +72,6 @@ int Input::getString(Common::String &line, uint maxLen, int maxWidth, bool isNum return line.size(); } -/** - * Draws the cursor and waits until the user presses a key - */ Common::KeyCode Input::doCursor(const Common::String &msg) { EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; diff --git a/engines/xeen/dialogs_input.h b/engines/xeen/dialogs_input.h index 2f30b73973..e824d17f57 100644 --- a/engines/xeen/dialogs_input.h +++ b/engines/xeen/dialogs_input.h @@ -31,11 +31,17 @@ namespace Xeen { class Input : public ButtonContainer { private: + /** + * Draws the cursor and waits until the user presses a key + */ Common::KeyCode doCursor(const Common::String &msg); protected: XeenEngine *_vm; Window *_window; + /** + * Allows the user to enter a string + */ int getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric); Input(XeenEngine *vm, Window *window) : _vm(vm), _window(window) {} diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index 147f934a61..4ad9e240bd 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -513,9 +513,6 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) { return c; } -/** - * Load the buttons for the dialog - */ void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) { _iconSprites.load(Common::String::format("%s.icn", (mode == ITEMMODE_CHAR_INFO) ? "items" : "buy")); @@ -580,11 +577,6 @@ void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) { } } -/** - * Loads the temporary _itemsCharacter character with the item set - * the given blacksmith has available, so the user can "view" the - * set as if it were a standard character's inventory - */ void ItemsDialog::blackData2CharData() { Party &party = *_vm->_party; bool isDarkCc = _vm->_files->_isDarkCc; @@ -602,10 +594,6 @@ void ItemsDialog::blackData2CharData() { } } -/** -* Saves the inventory from the temporary _itemsCharacter character back into the -* blacksmith storage, so changes in blacksmith inventory remain persistent -*/ void ItemsDialog::charData2BlackData() { Party &party = *_vm->_party; bool isDarkCc = _vm->_files->_isDarkCc; @@ -623,9 +611,6 @@ void ItemsDialog::charData2BlackData() { } } -/** - * Sets the equipment icon to use for each item for display - */ void ItemsDialog::setEquipmentIcons() { for (int typeIndex = 0; typeIndex < 4; ++typeIndex) { for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { @@ -676,9 +661,6 @@ void ItemsDialog::setEquipmentIcons() { } } -/** - * Calculate the cost of an item - */ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode, int skillLevel, ItemCategory category) { int amount1 = 0, amount2 = 0, amount3 = 0, amount4 = 0; diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h index bc995c52f8..6069ca823b 100644 --- a/engines/xeen/dialogs_items.h +++ b/engines/xeen/dialogs_items.h @@ -49,14 +49,32 @@ private: Character *execute(Character *c, ItemsMode mode); + /** + * Load the buttons for the dialog + */ void loadButtons(ItemsMode mode, Character *&c); + /** + * Loads the temporary _itemsCharacter character with the item set + * the given blacksmith has available, so the user can "view" the + * set as if it were a standard character's inventory + */ void blackData2CharData(); + /** + * Saves the inventory from the temporary _itemsCharacter character back into the + * blacksmith storage, so changes in blacksmith inventory remain persistent + */ void charData2BlackData(); + /** + * Sets the equipment icon to use for each item for display + */ void setEquipmentIcons(); + /** + * Calculate the cost of an item + */ int calcItemCost(Character *c, int itemIndex, ItemsMode mode, int skillLevel, ItemCategory category); diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index 69761bb4ec..18f5f3af10 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -295,9 +295,6 @@ void PartyDialog::setupBackground() { _vm->_interface->assembleBorder(); } -/** - * Sets up the faces from the avaialble roster for display in the party dialog - */ void PartyDialog::setupFaces(int firstDisplayChar, bool updateFlag) { Party &party = *_vm->_party; Common::String charNames[4]; @@ -765,10 +762,6 @@ int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) { return result == -1 ? 0 : result; } -/** - * Roll up some random values for the attributes, and return both them as - * well as a list of classes that the attributes meet the requirements for - */ void PartyDialog::throwDice(uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]) { bool repeat = true; do { @@ -793,10 +786,6 @@ void PartyDialog::throwDice(uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[ } while (repeat); } -/** - * Set a list of flags for which classes the passed attribute set meet the - * minimum requirements of - */ void PartyDialog::checkClass(const uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]) { allowedClasses[CLASS_KNIGHT] = attribs[MIGHT] >= 15; allowedClasses[CLASS_PALADIN] = attribs[MIGHT] >= 13 @@ -812,9 +801,6 @@ void PartyDialog::checkClass(const uint attribs[TOTAL_ATTRIBUTES], bool allowedC && attribs[ENDURANCE] >= 12 && attribs[SPEED] >= 12; } -/** - * Return details of the generated character - */ int PartyDialog::newCharDetails(const uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES], Race race, Sex sex, int classId, int selectedClass, Common::String &msg) { @@ -863,9 +849,6 @@ int PartyDialog::newCharDetails(const uint attribs[TOTAL_ATTRIBUTES], return classId == -1 ? foundClass : selectedClass; } -/** - * Print the selection arrow to indicate the selected class - */ void PartyDialog::printSelectionArrow(SpriteResource &icons, int selectedClass) { Window &w = _vm->_screen->_windows[0]; icons.draw(w, 61, Common::Point(220, 19)); @@ -873,9 +856,6 @@ void PartyDialog::printSelectionArrow(SpriteResource &icons, int selectedClass) w.update(); } -/** - * Print the dice animation - */ void PartyDialog::drawDice(SpriteResource &dice) { EventsManager &events = *_vm->_events; Window &w = _vm->_screen->_windows[32]; @@ -911,9 +891,6 @@ void PartyDialog::drawDice(SpriteResource &dice) { checkEvents(_vm); } -/** - * Exchanging two attributes for the character being rolled - */ int PartyDialog::exchangeAttribute(int srcAttr) { EventsManager &events = *_vm->_events; Screen &screen = *_vm->_screen; @@ -989,9 +966,6 @@ int PartyDialog::exchangeAttribute(int srcAttr) { return result; } -/** - * Saves the rolled character into the roster - */ bool PartyDialog::saveCharacter(Character &c, CharacterClass classId, Race race, Sex sex, uint attribs[TOTAL_ATTRIBUTES]) { if (classId == -1) { diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h index db2a3dfb36..2ad2daea0d 100644 --- a/engines/xeen/dialogs_party.h +++ b/engines/xeen/dialogs_party.h @@ -52,6 +52,9 @@ private: void setupBackground(); + /** + * Sets up the faces from the avaialble roster for display in the party dialog + */ void setupFaces(int firstDisplayChar, bool updateFlag); void startingCharChanged(int firstDisplayChar); @@ -60,20 +63,43 @@ private: int selectCharacter(bool isDelete, int firstDisplayChar); + /** + * Roll up some random values for the attributes, and return both them as + * well as a list of classes that the attributes meet the requirements for + */ void throwDice(uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]); + /** + * Set a list of flags for which classes the passed attribute set meet the + * minimum requirements of + */ void checkClass(const uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]); + /** + * Return details of the generated character + */ int newCharDetails(const uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES], Race race, Sex sex, int classId, int selectedClass, Common::String &msg); + /** + * Print the selection arrow to indicate the selected class + */ void printSelectionArrow(SpriteResource &icons, int selectedClass); + /** + * Print the dice animation + */ void drawDice(SpriteResource &dice); + /** + * Exchanging two attributes for the character being rolled + */ int exchangeAttribute(int srcAttr); + /** + * Saves the rolled character into the roster + */ bool saveCharacter(Character &c, CharacterClass classId, Race race, Sex sex, uint attribs[TOTAL_ATTRIBUTES]); public: diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp index 92dc8b487f..0c0a32be03 100644 --- a/engines/xeen/events.cpp +++ b/engines/xeen/events.cpp @@ -31,9 +31,6 @@ namespace Xeen { -/** - * Constructor - */ EventsManager::EventsManager(XeenEngine *vm) : _vm(vm), _frameCounter(0), _priorFrameCounterTime(0), _gameCounter(0), _priorGameCounterTime(0), _keyCode(Common::KEYCODE_INVALID), @@ -42,15 +39,9 @@ EventsManager::EventsManager(XeenEngine *vm) : _vm(vm), Common::fill(&_gameCounters[0], &_gameCounters[6], 0); } -/** - * Destructor - */ EventsManager::~EventsManager() { } -/* - * Set the cursor - */ void EventsManager::setCursor(int cursorId) { XSurface cursor; _sprites.draw(cursor, cursorId); @@ -59,23 +50,14 @@ void EventsManager::setCursor(int cursorId) { showCursor(); } -/** - * Show the mouse cursor - */ void EventsManager::showCursor() { CursorMan.showMouse(true); } -/** - * Hide the mouse cursor - */ void EventsManager::hideCursor() { CursorMan.showMouse(false); } -/** - * Returns if the mouse cursor is visible - */ bool EventsManager::isCursorVisible() { return CursorMan.isVisible(); } @@ -154,9 +136,6 @@ bool EventsManager::isKeyPending() const { return _keyCode != Common::KEYCODE_INVALID; } -/** - * Returns true if a key or mouse press is pending - */ bool EventsManager::isKeyMousePressed() { bool result = _leftButton || _rightButton || isKeyPending(); debounceMouse(); @@ -183,9 +162,6 @@ void EventsManager::ipause(uint amount) { } while (!_vm->shouldQuit() && timeElapsed() < amount); } -/** - * Handles moving to the next game frame - */ void EventsManager::nextFrame() { ++_frameCounter; diff --git a/engines/xeen/events.h b/engines/xeen/events.h index cce3155a4b..6ebe46e6fe 100644 --- a/engines/xeen/events.h +++ b/engines/xeen/events.h @@ -44,6 +44,9 @@ private: Common::KeyCode _keyCode; SpriteResource _sprites; + /** + * Handles moving to the next game frame + */ void nextFrame(); public: bool _leftButton, _rightButton; @@ -53,12 +56,24 @@ public: ~EventsManager(); + /* + * Set the cursor + */ void setCursor(int cursorId); + /** + * Show the mouse cursor + */ void showCursor(); + /** + * Hide the mouse cursor + */ void hideCursor(); + /** + * Returns if the mouse cursor is visible + */ bool isCursorVisible(); void pollEvents(); @@ -73,6 +88,9 @@ public: bool isKeyPending() const; + /** + * Returns true if a key or mouse press is pending + */ bool isKeyMousePressed(); void updateGameCounter() { _gameCounter = _frameCounter; } diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index 50949b7696..bcee6bf9f6 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -29,9 +29,6 @@ namespace Xeen { -/** -* Hash a given filename to produce the Id that represents it -*/ uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) { if (resourceName.empty()) return 0xffff; @@ -57,9 +54,6 @@ uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) { return total; } -/** -* Load the index of a given CC file -*/ void BaseCCArchive::loadIndex(Common::SeekableReadStream *stream) { int count = stream->readUint16LE(); @@ -95,10 +89,6 @@ bool BaseCCArchive::hasFile(const Common::String &name) const { return getHeaderEntry(name, ccEntry); } -/** -* Given a resource name, returns whether an entry exists, and returns -* the header index data for that entry -*/ bool BaseCCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const { uint16 id = convertNameToId(resourceName); @@ -193,9 +183,6 @@ Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::S /*------------------------------------------------------------------------*/ -/** - * Instantiates the resource manager - */ FileManager::FileManager(XeenEngine *vm) { Common::File f; int sideNum = 0; @@ -219,9 +206,6 @@ FileManager::FileManager(XeenEngine *vm) { /*------------------------------------------------------------------------*/ -/** - * Opens the given file, throwing an error if it can't be opened - */ void File::openFile(const Common::String &filename) { if (!Common::File::open(filename)) error("Could not open file - %s", filename.c_str()); diff --git a/engines/xeen/files.h b/engines/xeen/files.h index f0c92d1050..fc75031a72 100644 --- a/engines/xeen/files.h +++ b/engines/xeen/files.h @@ -56,6 +56,9 @@ public: bool _isDarkCc; CCArchive *_sideArchives[2]; public: + /** + * Instantiates the resource manager + */ FileManager(XeenEngine *vm); void setGameCc(bool isDarkCc) { _isDarkCc = isDarkCc; } @@ -73,7 +76,14 @@ public: } virtual ~File() {} + /** + * Opens the given file, throwing an error if it can't be opened + */ void openFile(const Common::String &filename); + + /** + * Opens the given file, throwing an error if it can't be opened + */ void openFile(const Common::String &filename, Common::Archive &archive); Common::String readString(); @@ -112,10 +122,20 @@ class BaseCCArchive : public Common::Archive { protected: Common::Array<CCEntry> _index; + /** + * Load the index of a given CC file + */ void loadIndex(Common::SeekableReadStream *stream); + /** + * Given a resource name, returns whether an entry exists, and returns + * the header index data for that entry + */ virtual bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const; public: + /** + * Hash a given filename to produce the Id that represents it + */ static uint16 convertNameToId(const Common::String &resourceName); public: BaseCCArchive() {} diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp index bfdc4bde6b..87e16b5bdd 100644 --- a/engines/xeen/font.cpp +++ b/engines/xeen/font.cpp @@ -37,10 +37,6 @@ FontSurface::FontSurface(int wv, int hv) : XSurface(wv, hv), _fontData(nullptr), setTextColor(0); } -/** - * Draws a symbol to the surface. - * @param symbolId Symbol number from 0 to 19 - */ void FontSurface::writeSymbol(int symbolId) { const byte *srcP = &SYMBOLS[symbolId][0]; @@ -57,14 +53,6 @@ void FontSurface::writeSymbol(int symbolId) { _writePos.x += 8; } -/** - * Write a string to the surface - * @param s String to display - * @param clipRect Window bounds to display string within - * @returns Any string remainder that couldn't be displayed - * @remarks Note that bounds is just used for wrapping purposes. Unless - * justification is set, the message will be written at _writePos - */ const char *FontSurface::writeString(const Common::String &s, const Common::Rect &bounds) { _displayString = s.c_str(); assert(_fontData); @@ -253,16 +241,10 @@ const char *FontSurface::writeString(const Common::String &s, const Common::Rect return _displayString; } -/** - * Return the next pending character to display - */ char FontSurface::getNextChar() { return *_displayString++ & 0x7f; } -/** -* Return the width of a given character -*/ bool FontSurface::getNextCharWidth(int &total) { char c = getNextChar(); @@ -292,9 +274,6 @@ bool FontSurface::getNextCharWidth(int &total) { } } -/** - * Handles moving to the next line of the given bounded area - */ bool FontSurface::newLine(const Common::Rect &bounds) { // Move past any spaces currently being pointed to while ((*_displayString & 0x7f) == ' ') @@ -309,9 +288,6 @@ bool FontSurface::newLine(const Common::Rect &bounds) { return ((_writePos.y + hv - 1) > bounds.bottom); } -/** - * Extract a number of a given maximum length from the string - */ int FontSurface::fontAtoi(int len) { int total = 0; for (int i = 0; i < len; ++i) { @@ -329,17 +305,11 @@ int FontSurface::fontAtoi(int len) { return total; } -/** - * Set the text colors based on the specified index in the master text colors list - */ void FontSurface::setTextColor(int idx) { const byte *colP = &TEXT_COLORS[idx][0]; Common::copy(colP, colP + 4, &_textColors[0]); } -/** - * Wrie a character to the surface - */ void FontSurface::writeChar(char c, const Common::Rect &clipRect) { // Get y position, handling kerning int y = _writePos.y; diff --git a/engines/xeen/font.h b/engines/xeen/font.h index caaa03c5ba..021205d5e5 100644 --- a/engines/xeen/font.h +++ b/engines/xeen/font.h @@ -38,16 +38,34 @@ private: const char *_displayString; bool _msgWraps; + /** + * Return the next pending character to display + */ char getNextChar(); + /** + * Return the width of a given character + */ bool getNextCharWidth(int &total); + /** + * Handles moving to the next line of the given bounded area + */ bool newLine(const Common::Rect &bounds); + /** + * Extract a number of a given maximum length from the string + */ int fontAtoi(int len = 3); + /** + * Set the text colors based on the specified index in the master text colors list + */ void setTextColor(int idx); + /** + * Wrie a character to the surface + */ void writeChar(char c, const Common::Rect &clipRect); public: const byte *_fontData; @@ -61,8 +79,20 @@ public: FontSurface(int wv, int hv); virtual ~FontSurface() {} + /** + * Draws a symbol to the surface. + * @param symbolId Symbol number from 0 to 19 + */ void writeSymbol(int symbolId); + /** + * Write a string to the surface + * @param s String to display + * @param clipRect Window bounds to display string within + * @returns Any string remainder that couldn't be displayed + * @remarks Note that bounds is just used for wrapping purposes. Unless + * justification is set, the message will be written at _writePos + */ const char *writeString(const Common::String &s, const Common::Rect &clipRect); }; diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index f9f1eebd10..3225831879 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -259,10 +259,6 @@ void Interface::setMainButtons(bool combatMode) { } } -/** - * Waits for a keypress or click, whilst still allowing the game scene to - * be animated. - */ void Interface::perform() { Combat &combat = *_vm->_combat; EventsManager &events = *_vm->_events; @@ -621,9 +617,6 @@ void Interface::chargeStep() { } } -/** - * Handles incrementing game time - */ void Interface::stepTime() { Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; @@ -714,9 +707,6 @@ void Interface::doStepCode() { } } -/** - * Start the party falling - */ void Interface::startFalling(bool flag) { Combat &combat = *_vm->_combat; Map &map = *_vm->_map; @@ -931,9 +921,6 @@ void Interface::startFalling(bool flag) { _flipGround ^= 1; } -/** - * Check movement in the given direction - */ bool Interface::checkMoveDirection(int key) { Map &map = *_vm->_map; Party &party = *_vm->_party; @@ -1316,9 +1303,6 @@ void Interface::draw3d(bool updateFlag, bool skipDelay) { events.wait(2); } -/** - * Handle doing the falling - */ void Interface::handleFalling() { Party &party = *_vm->_party; Screen &screen = *_vm->_screen; @@ -1375,19 +1359,13 @@ void Interface::saveFall() { } void Interface::fall(int v) { - + // TODO } -/** - * Shake the screen - */ void Interface::shake(int time) { - + // TODO } -/** - * Draw the minimap - */ void Interface::drawMiniMap() { Map &map = *_vm->_map; Party &party = *_vm->_party; @@ -1765,9 +1743,6 @@ void Interface::drawMiniMap() { party._wizardEyeActive = eyeActive; } -/** - * Draw the display borders - */ void Interface::assembleBorder() { Combat &combat = *_vm->_combat; Resources &res = *_vm->_resources; @@ -2186,9 +2161,6 @@ void Interface::doCombat() { combat._combatMode = COMBATMODE_1; } -/** - * Select next character or monster to be attacking - */ void Interface::nextChar() { Combat &combat = *_vm->_combat; Party &party = *_vm->_party; diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index 24edf9d23d..074d7fdafb 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -90,22 +90,40 @@ private: void chargeStep(); + /** + * Handles incrementing game time + */ void stepTime(); void doStepCode(); + /** + * Check movement in the given direction + */ bool checkMoveDirection(int key); + /** + * Handle doing the falling + */ void handleFalling(); void saveFall(); void fall(int v); + /** + * Shake the screen + */ void shake(int time); + /** + * Draw the minimap + */ void drawMiniMap(); + /** + * Select next character or monster to be attacking + */ void nextChar(); public: int _intrIndex1; @@ -133,8 +151,15 @@ public: void mainIconsPrint(); + /** + * Start the party falling + */ void startFalling(bool v); + /** + * Waits for a keypress or click, whilst still allowing the game scene to + * be animated. + */ void perform(); void rest(); @@ -143,6 +168,9 @@ public: void draw3d(bool updateFlag, bool skipDelay = false); + /** + * Draw the display borders + */ void assembleBorder(); void doCombat(); diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index a08ce808d8..f5bf2af187 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -690,10 +690,6 @@ void InterfaceMap::drawMap() { animate3d(); } -/** - * Handles animation of monsters, wall items, and combat within the 3d - * view by cycling the appropriate frame numbers - */ void InterfaceMap::animate3d() { Combat &combat = *_vm->_combat; Map &map = *_vm->_map; @@ -2304,9 +2300,6 @@ void InterfaceMap::setMazeBits() { } } -/** - * Set up draw structures for displaying on-screen monsters - */ void InterfaceMap::setIndoorsMonsters() { Combat &combat = *_vm->_combat; Map &map = *_vm->_map; @@ -2616,10 +2609,6 @@ void InterfaceMap::setIndoorsMonsters() { } } -/** - * Helper method for setIndoorsMonsters to set a draw structure - * with the deatils for a given monster - */ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, SpriteResource *sprites, int frame, int defaultY) { MonsterStruct &monsterData = *monster._monsterData; @@ -2641,9 +2630,6 @@ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster drawStruct._flags = MONSTER_EFFECT_FLAGS[monster._effect2][monster._effect3]; } -/** - * Set up draw structures for displaying on-screen objects - */ void InterfaceMap::setIndoorsObjects() { Common::Point mazePos = _vm->_party->_mazePosition; Direction dir = _vm->_party->_mazeDirection; @@ -2869,9 +2855,6 @@ void InterfaceMap::setIndoorsObjects() { } } -/** - * Set up draw structures for displaying on-screen wall items - */ void InterfaceMap::setIndoorsWallPics() { Map &map = *_vm->_map; const Common::Point &mazePos = _vm->_party->_mazePosition; @@ -3098,9 +3081,6 @@ void InterfaceMap::setIndoorsWallPics() { } } -/** - * Set up the draw structures for displaying monsters on outdoor maps - */ void InterfaceMap::setOutdoorsMonsters() { Combat &combat = *_vm->_combat; Map &map = *_vm->_map; @@ -3354,9 +3334,6 @@ void InterfaceMap::setOutdoorsMonsters() { // TODO } -/** - * Set up the draw structures for displaying objects on outdoor maps - */ void InterfaceMap::setOutdoorsObjects() { Map &map = *_vm->_map; Party &party = *_vm->_party; @@ -3544,9 +3521,6 @@ void InterfaceMap::setOutdoorsObjects() { } } -/** - * Draw the contents of the current 3d view of an indoor map - */ void InterfaceMap::drawIndoors() { Map &map = *_vm->_map; int surfaceId; @@ -4393,9 +4367,6 @@ void InterfaceMap::drawIndoors() { _charsShooting = _isAttacking; } -/** - * Draw the contents of the current 3d view of an outdoor map - */ void InterfaceMap::drawOutdoors() { Map &map = *_vm->_map; Party &party = *_vm->_party; diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h index a37bf349ec..2189aacec1 100644 --- a/engines/xeen/interface_map.h +++ b/engines/xeen/interface_map.h @@ -95,6 +95,10 @@ private: void initDrawStructs(); + /** + * Helper method for setIndoorsMonsters to set a draw structure + * with the deatils for a given monster + */ void setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, SpriteResource *sprites, int frame, int defaultY); protected: @@ -109,6 +113,10 @@ protected: void setMazeBits(); + /** + * Handles animation of monsters, wall items, and combat within the 3d + * view by cycling the appropriate frame numbers + */ void animate3d(); void drawMap(); @@ -126,18 +134,39 @@ public: virtual ~InterfaceMap() {} + /** + * Set up draw structures for displaying on-screen monsters + */ void setIndoorsMonsters(); + /** + * Set up draw structures for displaying on-screen objects + */ void setIndoorsObjects(); + /** + * Set up draw structures for displaying on-screen wall items + */ void setIndoorsWallPics(); + /** + * Draw the contents of the current 3d view of an indoor map + */ void drawIndoors(); + /** + * Set up the draw structures for displaying monsters on outdoor maps + */ void setOutdoorsMonsters(); + /** + * Set up the draw structures for displaying objects on outdoor maps + */ void setOutdoorsObjects(); + /** + * Draw the contents of the current 3d view of an outdoor map + */ void drawOutdoors(); }; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index ff7938746e..6816423a19 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -603,9 +603,6 @@ void MazeData::synchronize(Common::SeekableReadStream &s) { SavesManager::syncBitFlags(ser, &_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH]); } -/** - * Flags all tiles for the map as having been stepped on - */ void MazeData::setAllTilesStepped() { for (int y = 0; y < MAP_HEIGHT; ++y) Common::fill(&_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH], true); @@ -663,10 +660,6 @@ MazeMonster::MazeMonster() { _monsterData = nullptr; } -/** - * Return the text color to use when displaying the monster's name in combat - * to indicate how damaged they are - */ int MazeMonster::getTextColor() const { if (_hp == _monsterData->_hp) return 15; @@ -843,9 +836,6 @@ void HeadData::synchronize(Common::SeekableReadStream &s) { /*------------------------------------------------------------------------*/ -/** - * Synchronize data for an animation entry - */ void AnimationEntry::synchronize(Common::SeekableReadStream &s) { for (int i = 0; i < 4; ++i) _frame1._frames[i] = s.readByte(); @@ -855,9 +845,6 @@ void AnimationEntry::synchronize(Common::SeekableReadStream &s) { _frame2._frames[i] = s.readByte(); } -/** - * Synchronize data for object animations within the game - */ void AnimationInfo::synchronize(Common::SeekableReadStream &s) { AnimationEntry entry; @@ -868,9 +855,6 @@ void AnimationInfo::synchronize(Common::SeekableReadStream &s) { } } -/** - * Load the animation info objects in the game - */ void AnimationInfo::load(const Common::String &name) { File f(name); synchronize(f); @@ -1301,9 +1285,6 @@ int Map::mazeLookup(const Common::Point &pt, int layerShift, int wallMask) { } } -/** - * Load the events for a new map - */ void Map::loadEvents(int mapId) { // Load events Common::String filename = Common::String::format("maze%c%03d.evt", diff --git a/engines/xeen/map.h b/engines/xeen/map.h index a7e88c1726..2c02e6ed2f 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -210,6 +210,9 @@ public: void synchronize(Common::SeekableReadStream &s); + /** + * Flags all tiles for the map as having been stepped on + */ void setAllTilesStepped(); void clearCellSurfaces(); @@ -257,6 +260,10 @@ struct MazeMonster { MazeMonster(); + /** + * Return the text color to use when displaying the monster's name in combat + * to indicate how damaged they are + */ int getTextColor() const; }; @@ -341,13 +348,22 @@ struct AnimationEntry { int _frames[4]; } _frame2; + /** + * Synchronize data for an animation entry + */ void synchronize(Common::SeekableReadStream &s); }; class AnimationInfo : public Common::Array<AnimationEntry> { public: + /** + * Synchronize data for object animations within the game + */ void synchronize(Common::SeekableReadStream &s); + /** + * Load the animation info objects in the game + */ void load(const Common::String &name); }; @@ -361,6 +377,9 @@ private: int _sideMonsters; int _mazeDataIndex; + /** + * Load the events for a new map + */ void loadEvents(int mapId); public: Common::String _mazeName; diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk index de4df4a90f..b18f44fa6d 100644 --- a/engines/xeen/module.mk +++ b/engines/xeen/module.mk @@ -9,7 +9,6 @@ MODULE_OBJS := \ debugger.o \ detection.o \ dialogs.o \ - automap.o \ dialogs_automap.o \ dialogs_char_info.o \ dialogs_control_panel.o \ diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 1db4a14f59..35a8f00fbe 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -264,19 +264,12 @@ bool Party::isInParty(int charId) { return false; } -/** - * Copy the currently active party characters' data back to the roster - */ void Party::copyPartyToRoster() { for (uint i = 0; i < _activeParty.size(); ++i) { _roster[_activeParty[i]._rosterId] = _activeParty[i]; } } -/** - * Adds time to the party's playtime, taking into account the effect of any - * stat modifier changes - */ void Party::changeTime(int numMinutes) { bool killed = false; @@ -557,16 +550,10 @@ void Party::checkPartyDead() { _dead = true; } -/** - * Move party position to the run destination on the current map - */ void Party::moveToRunLocation() { _mazePosition = _vm->_map->mazeData()._runPosition; } -/** - * Give treasure to the party - */ void Party::giveTreasure() { Combat &combat = *_vm->_combat; EventsManager &events = *_vm->_events; @@ -691,9 +678,6 @@ void Party::giveTreasure() { scripts._v2 = 1; } -/** - * Returns true if all the packs for all the characters are full - */ bool Party::arePacksFull() const { uint total = 0; for (uint idx = 0; idx < _activeParty.size(); ++idx) { @@ -707,9 +691,6 @@ bool Party::arePacksFull() const { return total == (_activeParty.size() * NUM_ITEM_CATEGORIES); } -/** - * Give a treasure item to the given character's inventory - */ void Party::giveTreasureToCharacter(Character &c, ItemCategory category, int itemIndex) { EventsManager &events = *_vm->_events; Screen &screen = *_vm->_screen; diff --git a/engines/xeen/party.h b/engines/xeen/party.h index df6864da33..d753b75801 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -78,6 +78,9 @@ class Party { private: static XeenEngine *_vm; + /** + * Give a treasure item to the given character's inventory + */ void giveTreasureToCharacter(Character &c, ItemCategory category, int itemIndex); public: // Dynamic data that's saved @@ -153,8 +156,15 @@ public: bool isInParty(int charId); + /** + * Copy the currently active party characters' data back to the roster + */ void copyPartyToRoster(); + /** + * Adds time to the party's playtime, taking into account the effect of any + * stat modifier changes + */ void changeTime(int numMinutes); void addTime(int numMinutes); @@ -169,10 +179,19 @@ public: void checkPartyDead(); + /** + * Move party position to the run destination on the current map + */ void moveToRunLocation(); + /** + * Give treasure to the party + */ void giveTreasure(); + /** + * Returns true if all the packs for all the characters are full + */ bool arePacksFull() const; bool canShoot() const; diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index 61022a31cb..9fd2d19a9b 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -57,9 +57,6 @@ SavesManager::~SavesManager() { delete[] _data; } -/** - * Synchronizes a boolean array as a bitfield set - */ void SavesManager::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP) { byte data = 0; @@ -122,9 +119,6 @@ void SavesManager::load(Common::SeekableReadStream *stream) { delete pty; } -/** - * Sets up the dynamic data for the game for a new game - */ void SavesManager::reset() { Common::String prefix = _vm->getGameID() != GType_DarkSide ? "xeen|" : "dark|"; Common::MemoryWriteStreamDynamic saveFile(DisposeAfterUse::YES); diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h index 8f112f689e..2571c46600 100644 --- a/engines/xeen/saves.h +++ b/engines/xeen/saves.h @@ -64,6 +64,9 @@ private: void load(Common::SeekableReadStream *stream); public: + /** + * Synchronizes a boolean array as a bitfield set + */ static void syncBitFlags(Common::Serializer &s, bool *startP, bool *endP); public: bool _wonWorld; @@ -73,6 +76,9 @@ public: ~SavesManager(); + /** + * Sets up the dynamic data for the game for a new game + */ void reset(); void readCharFile(); diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index 80f0149d7c..a013b9706b 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -161,24 +161,15 @@ void Window::close() { } } -/** - * Update the window - */ void Window::update() { // Since all window drawing is done on the screen surface anyway, // there's nothing that needs to be updated here } -/** - * Adds an area that requires redrawing on the next frame update - */ void Window::addDirtyRect(const Common::Rect &r) { _vm->_screen->addDirtyRect(r); } -/** - * Fill the content area of a window with the current background color - */ void Window::fill() { fillRect(_innerBounds, _vm->_screen->_bgColor); } @@ -202,9 +193,6 @@ void Window::drawList(DrawStruct *items, int count) { /*------------------------------------------------------------------------*/ -/** - * Constructor - */ Screen::Screen(XeenEngine *vm) : _vm(vm) { _fadeIn = false; create(SCREEN_WIDTH, SCREEN_HEIGHT); @@ -337,18 +325,12 @@ bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, co return !destRect.isEmpty(); } -/** - * Load a palette resource into the temporary palette - */ void Screen::loadPalette(const Common::String &name) { File f(name); for (int i = 0; i < PALETTE_SIZE; ++i) _tempPalette[i] = f.readByte() << 2; } -/** - * Load a background resource into memory - */ void Screen::loadBackground(const Common::String &name) { File f(name); @@ -357,9 +339,6 @@ void Screen::loadBackground(const Common::String &name) { addDirtyRect(Common::Rect(0, 0, this->w, this->h)); } -/** - * Copy a loaded background into a display page - */ void Screen::loadPage(int pageNum) { assert(pageNum == 0 || pageNum == 1); if (_pages[0].empty()) { @@ -375,9 +354,6 @@ void Screen::freePages() { _pages[1].free(); } -/** - * Merge the two pages along a horizontal split point - */ void Screen::horizMerge(int xp) { if (_pages[0].empty()) return; @@ -394,9 +370,6 @@ void Screen::horizMerge(int xp) { } } -/** - * Merge the two pages along a vertical split point - */ void Screen::vertMerge(int yp) { if (_pages[0].empty()) return; @@ -420,9 +393,6 @@ void Screen::draw(void *data) { drawScreen(); } -/** - * Mark the entire screen for drawing - */ void Screen::drawScreen() { addDirtyRect(Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); } diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 21b7e8992e..4ab76d529d 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -86,10 +86,16 @@ public: void close(); + /** + * Update the window + */ void update(); void frame(); + /** + * Fill the content area of a window with the current background color + */ void fill(); const char *writeString(const Common::String &s); @@ -113,6 +119,9 @@ private: bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2); + /** + * Mark the entire screen for drawing + */ void drawScreen(); void fadeInner(int step); @@ -121,6 +130,9 @@ private: void updatePalette(const byte *pal, int start, int count16); public: + /** + * Adds an area that requires redrawing on the next frame update + */ virtual void addDirtyRect(const Common::Rect &r); public: Common::Array<Window> _windows; @@ -137,16 +149,31 @@ public: void update(); + /** + * Load a palette resource into the temporary palette + */ void loadPalette(const Common::String &name); + /** + * Load a background resource into memory + */ void loadBackground(const Common::String &name); + /** + * Copy a loaded background into a display page + */ void loadPage(int pageNum); void freePages(); + /** + * Merge the two pages along a horizontal split point + */ void horizMerge(int xp); + /** + * Merge the two pages along a vertical split point + */ void vertMerge(int yp); void draw(void *data = nullptr); diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 175292fa1d..177bb5d146 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -316,9 +316,6 @@ void Scripts::openGrate(int wallVal, int action) { typedef void(Scripts::*ScriptMethodPtr)(Common::Array<byte> &); -/** - * Handles executing a given script command - */ void Scripts::doOpcode(MazeEvent &event) { static const ScriptMethodPtr COMMAND_LIST[] = { nullptr, &Scripts::cmdDisplay1, &Scripts::cmdDoorTextSml, @@ -349,9 +346,6 @@ void Scripts::doOpcode(MazeEvent &event) { (this->*COMMAND_LIST[event._opcode])(event._parameters); } -/** - * Display a msesage on-screen - */ void Scripts::cmdDisplay1(Common::Array<byte> ¶ms) { Screen &screen = *_vm->_screen; Common::String paramText = _vm->_map->_events._text[_event->_parameters[0]]; @@ -366,9 +360,6 @@ void Scripts::cmdDisplay1(Common::Array<byte> ¶ms) { cmdNoAction(params); } -/** - * Displays a door text message using the small font - */ void Scripts::cmdDoorTextSml(Common::Array<byte> ¶ms) { Interface &intf = *_vm->_interface; @@ -381,9 +372,6 @@ void Scripts::cmdDoorTextSml(Common::Array<byte> ¶ms) { cmdNoAction(params); } -/** - * Displays a door text message using the large font - */ void Scripts::cmdDoorTextLrg(Common::Array<byte> ¶ms) { Interface &intf = *_vm->_interface; @@ -396,9 +384,6 @@ void Scripts::cmdDoorTextLrg(Common::Array<byte> ¶ms) { cmdNoAction(params); } -/** - * Show a sign text on-screen - */ void Scripts::cmdSignText(Common::Array<byte> ¶ms) { Interface &intf = *_vm->_interface; @@ -421,9 +406,6 @@ void Scripts::cmdNPC(Common::Array<byte> ¶ms) { cmdNoAction(params); } -/** - * Play a sound FX - */ void Scripts::cmdPlayFX(Common::Array<byte> ¶ms) { _vm->_sound->playFX(params[0]); @@ -496,9 +478,6 @@ void Scripts::cmdTeleport(Common::Array<byte> ¶ms) { } } -/** - * Do a conditional check - */ void Scripts::cmdIf(Common::Array<byte> ¶ms) { Party &party = *_vm->_party; uint32 mask; @@ -542,9 +521,6 @@ void Scripts::cmdIf(Common::Array<byte> ¶ms) { cmdNoAction(params); } -/** - * Moves the position of an object - */ void Scripts::cmdMoveObj(Common::Array<byte> ¶ms) { MazeObject &mazeObj = _vm->_map->_mobData._objects[params[0]]; @@ -765,9 +741,6 @@ void Scripts::cmdTakeOrGive(Common::Array<byte> ¶ms) { cmdNoAction(params); } -/** - * Move to the next line of the script - */ void Scripts::cmdNoAction(Common::Array<byte> ¶ms) { // Move to next line _lineNum = _vm->_party->_partyDead ? -1 : _lineNum + 1; @@ -786,9 +759,6 @@ void Scripts::cmdRemove(Common::Array<byte> ¶ms) { cmdMakeNothingHere(params); } -/** - * Set the currently active character for other script operations - */ void Scripts::cmdSetChar(Common::Array<byte> ¶ms) { if (params[0] != 7) { _charIndex = WhoWill::show(_vm, 22, 3, false); @@ -804,9 +774,6 @@ void Scripts::cmdSetChar(Common::Array<byte> ¶ms) { cmdNoAction(params); } -/** - * Spawn a monster - */ void Scripts::cmdSpawn(Common::Array<byte> ¶ms) { Map &map = *_vm->_map; if (params[0] >= map._mobData._monsters.size()) @@ -833,16 +800,10 @@ void Scripts::cmdDoTownEvent(Common::Array<byte> ¶ms) { cmdExit(params); } -/** - * Stop executing the script - */ void Scripts::cmdExit(Common::Array<byte> ¶ms) { _lineNum = -1; } -/** - * Changes the value for the wall on a given cell - */ void Scripts::cmdAlterMap(Common::Array<byte> ¶ms) { Map &map = *_vm->_map; @@ -970,9 +931,6 @@ void Scripts::cmdDamage(Common::Array<byte> ¶ms) { cmdNoAction(params); } -/** - * Jump if a random number matches a given value - */ void Scripts::cmdJumpRnd(Common::Array<byte> ¶ms) { int v = _vm->getRandomNumber(1, params[0]); if (v == params[1]) @@ -981,9 +939,6 @@ void Scripts::cmdJumpRnd(Common::Array<byte> ¶ms) { cmdNoAction(params); } -/** - * Alter an existing event - */ void Scripts::cmdAlterEvent(Common::Array<byte> ¶ms) { Map &map = *_vm->_map; Party &party = *_vm->_party; @@ -1000,10 +955,6 @@ void Scripts::cmdAlterEvent(Common::Array<byte> ¶ms) { cmdNoAction(params); } -/** - * Stores the current location and line for later resuming, and set up to execute - * a script at a given location - */ void Scripts::cmdCallEvent(Common::Array<byte> ¶ms) { _stack.push(StackEntry(_currentPos, _lineNum)); _currentPos = Common::Point(params[0], params[1]); @@ -1012,10 +963,6 @@ void Scripts::cmdCallEvent(Common::Array<byte> ¶ms) { cmdNoAction(params); } -/** - * Return from executing a script to the script location that previously - * called the script - */ void Scripts::cmdReturn(Common::Array<byte> ¶ms) { StackEntry &se = _stack.top(); _currentPos = se; @@ -1245,9 +1192,6 @@ void Scripts::cmdItemType(Common::Array<byte> ¶ms) { cmdNoAction(params); } -/** - * Disable all the scripts at the party's current position - */ void Scripts::cmdMakeNothingHere(Common::Array<byte> ¶ms) { Map &map = *_vm->_map; Party &party = *_vm->_party; @@ -1270,10 +1214,6 @@ void Scripts::cmdCheckProtection(Common::Array<byte> ¶ms) { cmdExit(params); } -/** - * Given a number of options, and a list of line numbers associated with - * those options, jumps to whichever line for the option the user selects - */ void Scripts::cmdChooseNumeric(Common::Array<byte> ¶ms) { int choice = Choose123::show(_vm, params[0]); if (choice) { @@ -1305,9 +1245,6 @@ void Scripts::cmdDisplayLarge(Common::Array<byte> ¶ms) { cmdNoAction(params); } -/** - * Exchange the positions of two objects in the maze - */ void Scripts::cmdExchObj(Common::Array<byte> ¶ms) { MazeObject &obj1 = _vm->_map->_mobData._objects[params[0]]; MazeObject &obj2 = _vm->_map->_mobData._objects[params[1]]; @@ -1335,11 +1272,6 @@ void Scripts::cmdDisplayMain(Common::Array<byte> ¶ms) { cmdNoAction(params); } -/** - * Jumps to a given line number if the surface at relative cell position 1 matches - * a specified surface. - * @remarks This opcode is apparently never actually used - */ void Scripts::cmdGoto(Common::Array<byte> ¶ms) { Map &map = *_vm->_map; map.getCell(1); @@ -1349,9 +1281,6 @@ void Scripts::cmdGoto(Common::Array<byte> ¶ms) { cmdNoAction(params); } -/** - * Pick a random value from the parameter list and jump to that line number - */ void Scripts::cmdGotoRandom(Common::Array<byte> ¶ms) { _lineNum = params[_vm->getRandomNumber(1, params[0])] - 1; cmdNoAction(params); @@ -1414,9 +1343,6 @@ void Scripts::doEnding(const Common::String &endStr, int v2) { warning("TODO: doEnding"); } -/** - * This monstrosity handles doing the various types of If checks on various data - */ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { Party &party = *_vm->_party; Character &ps = party._activeParty[charIndex]; diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 15550dd9c0..f41be1b7c6 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -155,30 +155,99 @@ private: Common::String _message; Common::String _displayMessage; + /** + * Handles executing a given script command + */ void doOpcode(MazeEvent &event); + + /** + * Display a msesage on-screen + */ void cmdDisplay1(Common::Array<byte> ¶ms); + + /** + * Displays a door text message using the small font + */ void cmdDoorTextSml(Common::Array<byte> ¶ms); + + /** + * Displays a door text message using the large font + */ void cmdDoorTextLrg(Common::Array<byte> ¶ms); + + /** + * Show a sign text on-screen + */ void cmdSignText(Common::Array<byte> ¶ms); void cmdNPC(Common::Array<byte> ¶ms); + + /** + * Play a sound FX + */ void cmdPlayFX(Common::Array<byte> ¶ms); void cmdTeleport(Common::Array<byte> ¶ms); + + /** + * Do a conditional check + */ void cmdIf(Common::Array<byte> ¶ms); + + /** + * Moves the position of an object + */ void cmdMoveObj(Common::Array<byte> ¶ms); void cmdTakeOrGive(Common::Array<byte> ¶ms); + + /** + * Move to the next line of the script + */ void cmdNoAction(Common::Array<byte> ¶ms); void cmdRemove(Common::Array<byte> ¶ms); + + /** + * Set the currently active character for other script operations + */ void cmdSetChar(Common::Array<byte> ¶ms); + + /** + * Spawn a monster + */ void cmdSpawn(Common::Array<byte> ¶ms); void cmdDoTownEvent(Common::Array<byte> ¶ms); + + /** + * Stop executing the script + */ void cmdExit(Common::Array<byte> ¶ms); + + /** + * Changes the value for the wall on a given cell + */ void cmdAlterMap(Common::Array<byte> ¶ms); void cmdGiveExtended(Common::Array<byte> ¶ms); void cmdConfirmWord(Common::Array<byte> ¶ms); void cmdDamage(Common::Array<byte> ¶ms); + + /** + * Jump if a random number matches a given value + */ void cmdJumpRnd(Common::Array<byte> ¶ms); + + /** + * Alter an existing event + */ void cmdAlterEvent(Common::Array<byte> ¶ms); + + /** + * Stores the current location and line for later resuming, and set up to execute + * a script at a given location + */ void cmdCallEvent(Common::Array<byte> ¶ms); + + /** + * Return from executing a script to the script location that previously + * called the script + */ void cmdReturn(Common::Array<byte> ¶ms); void cmdSetVar(Common::Array<byte> ¶ms); void cmdCutsceneEndClouds(Common::Array<byte> ¶ms); @@ -195,15 +264,38 @@ private: void cmdSelRndChar(Common::Array<byte> ¶ms); void cmdGiveEnchanted(Common::Array<byte> ¶ms); void cmdItemType(Common::Array<byte> ¶ms); + + /** + * Disable all the scripts at the party's current position + */ void cmdMakeNothingHere(Common::Array<byte> ¶ms); void cmdCheckProtection(Common::Array<byte> ¶ms); + + /** + * Given a number of options, and a list of line numbers associated with + * those options, jumps to whichever line for the option the user selects + */ void cmdChooseNumeric(Common::Array<byte> ¶ms); void cmdDisplayBottomTwoLines(Common::Array<byte> ¶ms); void cmdDisplayLarge(Common::Array<byte> ¶ms); + + /** + * Exchange the positions of two objects in the maze + */ void cmdExchObj(Common::Array<byte> ¶ms); void cmdFallToMap(Common::Array<byte> ¶ms); void cmdDisplayMain(Common::Array<byte> ¶ms); + + /** + * Jumps to a given line number if the surface at relative cell position 1 matches + * a specified surface. + * @remarks This opcode is apparently never actually used + */ void cmdGoto(Common::Array<byte> ¶ms); + + /** + * Pick a random value from the parameter list and jump to that line number + */ void cmdGotoRandom(Common::Array<byte> ¶ms); void cmdCutsceneEndDarkside(Common::Array<byte> ¶ms); void cmdCutsceneEdWorld(Common::Array<byte> ¶ms); @@ -220,6 +312,9 @@ private: void doEnding(const Common::String &endStr, int v2); + /** + * This monstrosity handles doing the various types of If checks on various data + */ bool ifProc(int action, uint32 mask, int mode, int charIndex); bool copyProtectionCheck(); diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index ba4e78bfb9..ee3085d052 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -88,16 +88,10 @@ void Spells::executeSpell(MagicSpell spellId) { (this->*SPELL_LIST[spellId])(); } -/** - * Spell being cast failed - */ void Spells::spellFailed() { ErrorScroll::show(_vm, SPELL_FAILED, WT_NONFREEZED_WAIT); } -/** - * Cast a spell associated with an item - */ void Spells::castItemSpell(int itemSpellId) { switch (itemSpellId) { case 15: @@ -170,9 +164,6 @@ void Spells::castItemSpell(int itemSpellId) { executeSpell(spells[itemSpellId]); } -/** - * Cast a given spell - */ int Spells::castSpell(Character *c, MagicSpell spellId) { Combat &combat = *_vm->_combat; Interface &intf = *_vm->_interface; @@ -217,10 +208,6 @@ int Spells::castSpell(Character *c, MagicSpell spellId) { return result; } -/** - * Subtract the requirements for a given spell if available, returning - * true if there was sufficient - */ int Spells::subSpellCost(Character &c, int spellId) { Party &party = *_vm->_party; int gemCost = SPELL_GEM_COST[spellId]; @@ -243,10 +230,6 @@ int Spells::subSpellCost(Character &c, int spellId) { return 0; } -/** - * Add the SP and gem requirements for a given spell to the given - * character and party - */ void Spells::addSpellCost(Character &c, int spellId) { Party &party = *_vm->_party; int gemCost = SPELL_GEM_COST[spellId]; diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h index 1af4fb222f..a05e81c56d 100644 --- a/engines/xeen/spells.h +++ b/engines/xeen/spells.h @@ -69,6 +69,9 @@ private: void executeSpell(MagicSpell spellId); + /** + * Spell being cast failed + */ void spellFailed(); // Spell list @@ -160,12 +163,26 @@ public: int calcSpellPoints(int spellId, int expenseFactor) const; + /** + * Cast a spell associated with an item + */ void castItemSpell(int itemSpellId); + /** + * Cast a given spell + */ int castSpell(Character *c, MagicSpell spellId); + /** + * Subtract the requirements for a given spell if available, returning + * true if there was sufficient + */ int subSpellCost(Character &c, int spellId); + /** + * Add the SP and gem requirements for a given spell to the given + * character and party + */ void addSpellCost(Character &c, int spellId); }; diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index b29fb2d053..4804f0aa66 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -51,9 +51,6 @@ SpriteResource::~SpriteResource() { clear(); } -/** - * Copy operator for duplicating a sprite resource - */ SpriteResource &SpriteResource::operator=(const SpriteResource &src) { delete[] _data; _index.clear(); @@ -69,25 +66,16 @@ SpriteResource &SpriteResource::operator=(const SpriteResource &src) { return *this; } -/** - * Load a sprite resource from a given file - */ void SpriteResource::load(const Common::String &filename) { File f(filename); load(f); } -/** - * Load a sprite resource from a given file and archive - */ void SpriteResource::load(const Common::String &filename, Common::Archive &archive) { File f(filename, archive); load(f); } -/** - * Load a sprite resource from a stream - */ void SpriteResource::load(Common::SeekableReadStream &f) { // Read in a copy of the file _filesize = f.size(); @@ -106,18 +94,12 @@ void SpriteResource::load(Common::SeekableReadStream &f) { } } -/** - * Clears the sprite resource - */ void SpriteResource::clear() { delete[] _data; _data = nullptr; _filesize = 0; } -/** - * Draws a frame using data at a specific offset in the sprite resource - */ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &pt, const Common::Rect &bounds, int flags, int scale) { static const uint SCALE_TABLE[] = { diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index 2a00ecaf76..9a241c2100 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -48,6 +48,9 @@ private: bool _lineDist[320]; int _scaledWidth, _scaledHeight; + /** + * Load a sprite resource from a stream + */ void load(Common::SeekableReadStream &f); /** @@ -72,12 +75,24 @@ public: virtual ~SpriteResource(); + /** + * Copy operator for duplicating a sprite resource + */ SpriteResource &operator=(const SpriteResource &src); + /** + * Load a sprite resource from a given file + */ void load(const Common::String &filename); + /** + * Load a sprite resource from a given file and archive + */ void load(const Common::String &filename, Common::Archive &archive); + /** + * Clears the sprite resource + */ void clear(); void draw(XSurface &dest, int frame, const Common::Point &destPos, diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 221f5d9978..52fa988e15 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -1184,9 +1184,6 @@ void Town::drawTownAnim(bool flag) { screen._windows[3].update(); } -/** - * Returns true if a town location (bank, blacksmith, etc.) is currently active - */ bool Town::isActive() const { return _townSprites.size() > 0 && !_townSprites[0].empty(); } diff --git a/engines/xeen/town.h b/engines/xeen/town.h index c64ef891f1..f56f24ca73 100644 --- a/engines/xeen/town.h +++ b/engines/xeen/town.h @@ -104,6 +104,9 @@ public: void drawTownAnim(bool flag); + /** + * Returns true if a town location (bank, blacksmith, etc.) is currently active + */ bool isActive() const; void clearSprites(); diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 3b317f52d6..da7810c4cb 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -271,9 +271,6 @@ void XeenEngine::showMainMenu() { //OptionsMenu::show(this); } -/** - * Main method for playing the game - */ void XeenEngine::playGame() { _saves->reset(); play(); diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index cd1b98b1b8..389d73dcc3 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -115,21 +115,21 @@ protected: virtual void showIntro() = 0; /** - * Play the game - */ + * Play the game + */ virtual void playGame(); private: void initialize(); /** - * Synchronize savegame data - */ + * Synchronize savegame data + */ void synchronize(Common::Serializer &s); /** - * Support method that generates a savegame name - * @param slot Slot number - */ + * Support method that generates a savegame name + * @param slot Slot number + */ Common::String generateSaveName(int slot); // Engine APIs -- cgit v1.2.3 From 6dc1551d7db3356868cb9402bcc9e9b75648f52b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 28 Aug 2016 18:16:48 -0400 Subject: XEEN: gcc compilation fixes --- engines/xeen/dialogs_input.cpp | 2 +- engines/xeen/dialogs_options.cpp | 4 ++-- engines/xeen/dialogs_query.cpp | 6 +++--- engines/xeen/dialogs_spells.cpp | 2 ++ engines/xeen/interface.cpp | 4 ++++ engines/xeen/interface_map.cpp | 2 -- engines/xeen/scripts.cpp | 6 +++++- 7 files changed, 17 insertions(+), 9 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_input.cpp b/engines/xeen/dialogs_input.cpp index 5833733353..40b8847d14 100644 --- a/engines/xeen/dialogs_input.cpp +++ b/engines/xeen/dialogs_input.cpp @@ -37,7 +37,7 @@ int Input::show(XeenEngine *vm, Window *window, Common::String &line, int Input::getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric) { _vm->_noDirectionSense = true; - Common::String msg = Common::String::format("\x3""l\t000\x4%03d\x0""c", maxWidth); + Common::String msg = Common::String::format("\x3""l\t000\x4%03d\x3""c", maxWidth); _window->writeString(msg); _window->update(); diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp index 4b4974b9aa..757634a2ad 100644 --- a/engines/xeen/dialogs_options.cpp +++ b/engines/xeen/dialogs_options.cpp @@ -110,7 +110,7 @@ void OptionsMenu::showTitles1(SpriteResource &sprites) { while (!_vm->shouldQuit() && !events.isKeyMousePressed()) { events.updateGameCounter(); - frameNum = ++frameNum % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10); + frameNum = (frameNum + 1) % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10); screen.restoreBackground(); sprites.draw(screen, frameNum); @@ -211,7 +211,7 @@ void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) { events.updateGameCounter(); // Draw the background frame in a continous cycle - _bgFrame = ++_bgFrame % 5; + _bgFrame = (_bgFrame + 1) % 5; title1.draw(screen._windows[0], _bgFrame); // Draw the basic frame for the optitons menu and title text diff --git a/engines/xeen/dialogs_query.cpp b/engines/xeen/dialogs_query.cpp index c982b8acd2..abaddafe69 100644 --- a/engines/xeen/dialogs_query.cpp +++ b/engines/xeen/dialogs_query.cpp @@ -105,7 +105,7 @@ bool YesNo::execute(bool type, bool townFlag) { Screen &screen = *_vm->_screen; Town &town = *_vm->_town; SpriteResource confirmSprites; - int numFrames; + //int numFrames; bool result = false; Mode oldMode = _vm->_mode; @@ -130,10 +130,10 @@ bool YesNo::execute(bool type, bool townFlag) { if (town.isActive()) { town.drawTownAnim(townFlag); - numFrames = 3; + //numFrames = 3; } else { intf.draw3d(true); - numFrames = 1; + //numFrames = 1; } events.wait(3, true); diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 7cde5f37ef..b17555260d 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -912,6 +912,8 @@ int Teleport::execute() { case DIR_WEST: pt.x -= numSquares; break; + default: + break; } v = map.mazeLookup(pt, map._isOutdoors ? 0xF : 0xFFFF, 0); diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 3225831879..9f9df190f7 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -513,6 +513,8 @@ void Interface::perform() { case DIR_WEST: --party._mazePosition.x; break; + default: + break; } chargeStep(); stepTime(); @@ -1230,6 +1232,8 @@ void Interface::bash(const Common::Point &pt, Direction direction) { case DIR_WEST: map.setWall(Common::Point(pt.x - 1, pt.y), DIR_EAST, 3); break; + default: + break; } } } diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index f5bf2af187..6dd98efefd 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -27,8 +27,6 @@ namespace Xeen { -static bool debugFlag = false; - OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]), _groundSprite(_data[2]), _attackImgs1(&_data[124]), _attackImgs2(&_data[95]), _attackImgs3(&_data[76]), _attackImgs4(&_data[53]), _groundTiles(&_data[3]) { diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 177bb5d146..03a24b434a 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -304,6 +304,8 @@ void Scripts::openGrate(int wallVal, int action) { case DIR_WEST: pt.x--; break; + default: + break; } map.setCellSurfaceFlags(pt, 0x80); @@ -1084,7 +1086,7 @@ void Scripts::cmdSeatTextSml(Common::Array<byte> ¶ms) { Interface &intf = *_vm->_interface; intf._screenText = Common::String::format("\x2\f08\x3""c\t116\v090%s\x3l\fd\x1", - _message); + _message.c_str()); intf._upDoorText = true; intf.draw3d(true); @@ -1227,7 +1229,9 @@ void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> ¶ms) { Map &map = *_vm->_map; Window &w = _vm->_screen->_windows[12]; + warning("TODO: cmdDisplayBottomTwoLines"); Common::String msg = Common::String::format("\r\x03c\t000\v007%s\n\n%s", + "", map._events._text[params[1]].c_str()); w.close(); w.open(); -- cgit v1.2.3 From 63a4201541df77afcf71fffb67516f40a8c169ba Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 3 Sep 2016 16:47:05 -0400 Subject: XEEN: Change a strncpy use to Common::strlcpy --- engines/xeen/character.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/xeen') diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index 2ab532938b..b0502d254a 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -724,7 +724,7 @@ void Character::clear() { void Character::synchronize(Common::Serializer &s) { char name[16]; Common::fill(&name[0], &name[16], '\0'); - strncpy(name, _name.c_str(), 16); + Common::strlcpy(name, _name.c_str(), 16); s.syncBytes((byte *)name, 16); if (s.isLoading()) -- cgit v1.2.3 From 0c948b6bd0fc87cb57ee8939228435921a504803 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 4 Sep 2016 14:19:05 -0400 Subject: XEEN: Fix Travis identified warnings --- engines/xeen/combat.h | 2 +- engines/xeen/dialogs_spells.cpp | 7 ++++--- engines/xeen/events.cpp | 5 ++--- engines/xeen/events.h | 1 - engines/xeen/interface_map.cpp | 4 +++- engines/xeen/resources.cpp | 2 -- engines/xeen/scripts.cpp | 4 ++-- engines/xeen/sound.cpp | 2 +- engines/xeen/sound.h | 1 - engines/xeen/xeen.cpp | 4 ++-- engines/xeen/xsurface.cpp | 7 ++++--- engines/xeen/xsurface.h | 4 ++-- 12 files changed, 21 insertions(+), 22 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 1a1fc3a41b..8a7c676018 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -31,7 +31,7 @@ namespace Xeen { #define MAX_NUM_MONSTERS 107 -#define PARTY_AND_MONSTERS 11 +#define PARTY_AND_MONSTERS 12 enum DamageType { DT_PHYSICAL = 0, DT_MAGICAL = 1, DT_FIRE = 2, DT_ELECTRICAL = 3, diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index b17555260d..a10dab650b 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -191,8 +191,8 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int case Common::KEYCODE_7: case Common::KEYCODE_8: case Common::KEYCODE_9: - newSelection = topIndex + (_buttonValue == Common::KEYCODE_0) ? 9 : - (_buttonValue - Common::KEYCODE_1); + newSelection = topIndex + ((_buttonValue == Common::KEYCODE_0) ? 9 : + (_buttonValue - Common::KEYCODE_1)); if (newSelection < (int)_spells.size()) { int expenseFactor = 0; @@ -224,6 +224,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int break; } + warning("TODO: category -> SPELLS_ALLOWED category value"); int spellId = _spells[newSelection]._spellId; int spellIndex = _spells[newSelection]._spellIndex; int spellCost = spells.calcSpellCost(spellId, expenseFactor); @@ -233,7 +234,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int Common::String spellName = _spells[newSelection]._name; Common::String msg = (castingCopy & 0x80) ? Common::String::format(SPELLS_PRESS_A_KEY, msg.c_str()) : - Common::String::format(SPELLS_PURCHASE, msg.c_str(), spellCost); + Common::String::format(SPELLS_PURCHASE, spellName.c_str(), spellCost); if (Confirm::show(_vm, msg, castingCopy + 1)) { if (party.subtract(0, spellCost, 0, WT_FREEZE_WAIT)) { diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp index 0c0a32be03..e50d689d9f 100644 --- a/engines/xeen/events.cpp +++ b/engines/xeen/events.cpp @@ -33,9 +33,8 @@ namespace Xeen { EventsManager::EventsManager(XeenEngine *vm) : _vm(vm), _frameCounter(0), _priorFrameCounterTime(0), _gameCounter(0), - _priorGameCounterTime(0), _keyCode(Common::KEYCODE_INVALID), - _leftButton(false), _rightButton(false), - _sprites("mouse.icn") { + _leftButton(false), _rightButton(false), _sprites("mouse.icn"), + _keyCode(Common::KEYCODE_INVALID) { Common::fill(&_gameCounters[0], &_gameCounters[6], 0); } diff --git a/engines/xeen/events.h b/engines/xeen/events.h index 6ebe46e6fe..7847ecd81c 100644 --- a/engines/xeen/events.h +++ b/engines/xeen/events.h @@ -40,7 +40,6 @@ private: uint32 _priorFrameCounterTime; uint32 _gameCounter; uint32 _gameCounters[6]; - uint32 _priorGameCounterTime; Common::KeyCode _keyCode; SpriteResource _sprites; diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp index 6dd98efefd..af39f38c28 100644 --- a/engines/xeen/interface_map.cpp +++ b/engines/xeen/interface_map.cpp @@ -525,6 +525,8 @@ void InterfaceMap::drawMap() { _outdoorList[116]._sprites = nullptr; _outdoorList[117]._sprites = nullptr; monsterIndex = 3; + } else { + monsterIndex = 0; } drawOutdoors(); @@ -1157,7 +1159,7 @@ void InterfaceMap::setMazeBits() { ++_wo[143]; break; case 9: - ++_wo[3033]; + ++_wo[303]; break; case 10: ++_wo[243]; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 0b30ce3e8b..c171a1717b 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1534,8 +1534,6 @@ const char *const X_FOUND_Y = "\v060\t000\x3""c%s found: %s"; const char *const ON_WHO = "\x3""c\v009On Who?"; -const char *const WHICH_ELEMENT = ""; - const char *const WHICH_ELEMENT1 = "\r\x3""c\x1Which Element?\x2\v034\t014\f15F\fdire\t044" "\f15E\fdlec\t074\f15C\fdold\t104\f15A\fdcid\x1"; diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 03a24b434a..0e752529d5 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -1172,7 +1172,7 @@ void Scripts::cmdGiveEnchanted(Common::Array<byte> ¶ms) { cmdNoAction(params); return; } else { - party._gameFlags[6 + params[0]]++; + party._gameFlags[6 + params[0]] = true; } } @@ -1435,7 +1435,7 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { // Check if the character class can cast the particular spell for (int idx = 0; idx < 39; ++idx) { - if (SPELLS_ALLOWED[mode][idx] == mask) { + if (SPELLS_ALLOWED[category][idx] == mask) { // Can cast it. Check if the player has it in their spellbook if (ps._spells[idx]) v = mask; diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp index c0a49aeb22..2aed7da45b 100644 --- a/engines/xeen/sound.cpp +++ b/engines/xeen/sound.cpp @@ -47,7 +47,7 @@ void VOC::stop() { /*------------------------------------------------------------------------*/ -SoundManager::SoundManager(XeenEngine *vm, Audio::Mixer *mixer): _vm(vm), _mixer(mixer) { +SoundManager::SoundManager(XeenEngine *vm, Audio::Mixer *mixer): _mixer(mixer) { } void SoundManager::proc2(Common::SeekableReadStream &f) { diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index bcee6f2f45..96b02c4efe 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -56,7 +56,6 @@ public: class SoundManager { private: - XeenEngine *_vm; Audio::Mixer *_mixer; public: SoundManager(XeenEngine *vm, Audio::Mixer *mixer); diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index da7810c4cb..066f238fed 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -335,8 +335,8 @@ void XeenEngine::gameLoop() { } Common::String XeenEngine::printMil(uint value) { - return (value >= 1000000) ? Common::String::format("%lu mil", value / 1000000) : - Common::String::format("%lu", value); + return (value >= 1000000) ? Common::String::format("%u mil", value / 1000000) : + Common::String::format("%u", value); } Common::String XeenEngine::printK(uint value) { diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp index 00d333d6d8..1793d76129 100644 --- a/engines/xeen/xsurface.cpp +++ b/engines/xeen/xsurface.cpp @@ -31,7 +31,8 @@ namespace Xeen { XSurface::XSurface() : Graphics::Surface(), _freeFlag(false) { } -XSurface::XSurface(int w, int h) : Graphics::Surface(), _freeFlag(false) { +XSurface::XSurface(int width, int height) : Graphics::Surface(), + _freeFlag(false) { create(w, h); } @@ -40,8 +41,8 @@ XSurface::~XSurface() { free(); } -void XSurface::create(uint16 w_, uint16 h_) { - Graphics::Surface::create(w_, h_, Graphics::PixelFormat::createFormatCLUT8()); +void XSurface::create(uint16 width, uint16 height) { + Graphics::Surface::create(width, height, Graphics::PixelFormat::createFormatCLUT8()); _freeFlag = true; } diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h index 299cc51f1d..f562112e5c 100644 --- a/engines/xeen/xsurface.h +++ b/engines/xeen/xsurface.h @@ -37,10 +37,10 @@ public: virtual void addDirtyRect(const Common::Rect &r) {} public: XSurface(); - XSurface(int w, int h); + XSurface(int width, int height); virtual ~XSurface(); - void create(uint16 w_, uint16 h_); + void create(uint16 width, uint16 height); void create(XSurface *s, const Common::Rect &bounds); -- cgit v1.2.3 From 12d57ad5fe48568a8d67665ed285c9d591590d1a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 4 Sep 2016 16:52:35 -0400 Subject: XEEN: Beginnings of Darkside endgame and music --- engines/xeen/sound.cpp | 41 ++++++++++++++++++++----- engines/xeen/sound.h | 37 +++++++++++++++++++--- engines/xeen/town.cpp | 2 +- engines/xeen/worldofxeen/darkside_cutscenes.cpp | 21 +++++++++++-- engines/xeen/xeen.cpp | 3 +- 5 files changed, 87 insertions(+), 17 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp index 2aed7da45b..f5cc40249d 100644 --- a/engines/xeen/sound.cpp +++ b/engines/xeen/sound.cpp @@ -26,22 +26,43 @@ namespace Xeen { -SoundManager *VOC::_sound; +SoundManager *Voc::_sound; -VOC::VOC(const Common::String &name) { +Voc::Voc(const Common::String &name) { if (!open(name)) error("Could not open - %s", name.c_str()); } -void VOC::init(XeenEngine *vm) { +void Voc::init(XeenEngine *vm) { _sound = vm->_sound; } -void VOC::play() { +void Voc::play() { _sound->playSound(this, _soundHandle); } -void VOC::stop() { +void Voc::stop() { + _sound->stopSound(_soundHandle); +} + +/*------------------------------------------------------------------------*/ + +SoundManager *Music::_sound; + +Music::Music(const Common::String &name) { + if (!open(name)) + error("Could not open - %s", name.c_str()); +} + +void Music::init(XeenEngine *vm) { + _sound = vm->_sound; +} + +void Music::play() { + _sound->playMusic(this, _soundHandle); +} + +void Music::stop() { _sound->stopSound(_soundHandle); } @@ -62,10 +83,14 @@ void SoundManager::stopMusic(int id) { // TODO } -void SoundManager::playSound(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle) { +void SoundManager::playSound(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle, + Audio::Mixer::SoundType soundType) { Audio::SeekableAudioStream *stream = Audio::makeVOCStream(s, 0); - _mixer->playStream(Audio::Mixer::kPlainSoundType, &soundHandle, stream); - + _mixer->playStream(soundType, &soundHandle, stream); +} + +void SoundManager::playMusic(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle) { + // TODO } void SoundManager::stopSound(Audio::SoundHandle &soundHandle) { diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h index 96b02c4efe..954d324e8d 100644 --- a/engines/xeen/sound.h +++ b/engines/xeen/sound.h @@ -33,14 +33,14 @@ namespace Xeen { class SoundManager; -class VOC: public Common::File { +class Voc: public Common::File { private: static SoundManager *_sound; Audio::SoundHandle _soundHandle; public: - VOC() {} - VOC(const Common::String &name); - virtual ~VOC() { stop(); } + Voc() {} + Voc(const Common::String &name); + virtual ~Voc() { stop(); } static void init(XeenEngine *vm); /** @@ -54,6 +54,27 @@ public: void stop(); }; +class Music : public Common::File { +private: + static SoundManager *_sound; + Audio::SoundHandle _soundHandle; +public: + Music() {} + Music(const Common::String &name); + virtual ~Music() { stop(); } + static void init(XeenEngine *vm); + + /** + * Start playing the sound + */ + void play(); + + /** + * Stop playing the sound + */ + void stop(); +}; + class SoundManager { private: Audio::Mixer *_mixer; @@ -73,7 +94,13 @@ public: /** * Play a given sound */ - void playSound(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle); + void playSound(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle, + Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType); + + /** + * Play a given music + */ + void playMusic(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle); /** * Stop playing a sound diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp index 52fa988e15..cc83563de2 100644 --- a/engines/xeen/town.cpp +++ b/engines/xeen/town.cpp @@ -825,7 +825,7 @@ Character *Town::doTempleOptions(Character *c) { intf.drawParty(true); sound.playSample(nullptr, 0); - VOC voc("ahh.voc"); + Voc voc("ahh.voc"); voc.play(); _flag1 = true; _donation = 0; diff --git a/engines/xeen/worldofxeen/darkside_cutscenes.cpp b/engines/xeen/worldofxeen/darkside_cutscenes.cpp index 6226b52a11..a5de6559c4 100644 --- a/engines/xeen/worldofxeen/darkside_cutscenes.cpp +++ b/engines/xeen/worldofxeen/darkside_cutscenes.cpp @@ -39,7 +39,7 @@ bool DarkSideCutscenes::showDarkSideTitle() { SpriteResource("nwc1.int"), SpriteResource("nwc2.int"), SpriteResource("nwc3.int"), SpriteResource("nwc4.int") }; - VOC voc[3]; + Voc voc[3]; voc[0].open("dragon1.voc"); voc[1].open("dragon2.voc"); voc[2].open("dragon3.voc"); @@ -158,7 +158,7 @@ bool DarkSideCutscenes::showDarkSideIntro() { SpriteResource sprites[3] = { SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int") }; - Common::File voc[2]; + Voc voc[2]; voc[0].open("pharoh1a.voc"); voc[1].open("pharoh1b.voc"); @@ -234,7 +234,24 @@ bool DarkSideCutscenes::showDarkSideIntro() { } bool DarkSideCutscenes::showDarkSideEnding() { + EventsManager &events = *_vm->_events; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + + Voc voc("ido2.voc"); + Music newBright("newbrigh.m"); + SpriteResource box("box.vga"); + + newBright.play(); + screen.loadBackground("scene1.raw"); + screen.loadPalette("endgame.pal"); + screen.update(); + + screen.fadeIn(4); + events.updateGameCounter(); + // TODO + events.wait(5000); return true; } diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 066f238fed..e549c8e845 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -98,7 +98,8 @@ void XeenEngine::initialize() { _sound = new SoundManager(this, _mixer); _spells = new Spells(this); _town = new Town(this); - VOC::init(this); + Voc::init(this); + Music::init(this); File f("029.obj"); _eventData = f.readStream(f.size()); -- cgit v1.2.3 From 94e1b960c416d1089a94539706cef858f80f9772 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 4 Sep 2016 21:16:51 -0400 Subject: XEEN: Converted XSurface to derive from ManagedSurface --- engines/xeen/screen.cpp | 15 ++++++++++++--- engines/xeen/screen.h | 2 +- engines/xeen/xsurface.cpp | 46 ---------------------------------------------- engines/xeen/xsurface.h | 31 ++++++++++++++----------------- 4 files changed, 27 insertions(+), 67 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index a013b9706b..e1e7b50a56 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -33,12 +33,21 @@ Window::Window() : _vm(nullptr), _enabled(false), _a(0), _border(0), _xLo(0), _xHi(0), _ycL(0), _ycH(0) { } +Window::Window(const Window &src) : _vm(src._vm), _enabled(src._enabled), + _a(src._a), _border(src._border), _xLo(src._xLo), _ycL(src._ycL), + _xHi(src._xHi), _ycH(src._ycH) { + if (src._vm) { + setBounds(src._bounds); + create(*_vm->_screen, Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + } +} + Window::Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border, int xLo, int ycL, int xHi, int ycH): _vm(vm), _enabled(false), _a(a), _border(border), _xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) { setBounds(bounds); - create(_vm->_screen, Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + create(*_vm->_screen, Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); } void Window::setBounds(const Common::Rect &r) { @@ -346,7 +355,7 @@ void Screen::loadPage(int pageNum) { _pages[1].create(SCREEN_WIDTH, SCREEN_HEIGHT); } - blitTo(_pages[pageNum]); + _pages[pageNum].blitFrom(*this); } void Screen::freePages() { @@ -447,7 +456,7 @@ void Screen::saveBackground(int slot) { void Screen::restoreBackground(int slot) { assert(slot > 0 && slot < 10); - _savedScreens[slot - 1].blitTo(*this); + blitFrom(_savedScreens[slot - 1]); } void Screen::frameWindow(uint bgType) { diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h index 4ab76d529d..854a05a7cf 100644 --- a/engines/xeen/screen.h +++ b/engines/xeen/screen.h @@ -74,7 +74,7 @@ public: virtual void addDirtyRect(const Common::Rect &r); public: Window(); - + Window(const Window &src); Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border, int xLo, int ycL, int xHi, int ycH); diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp index 1793d76129..5f10a83dc6 100644 --- a/engines/xeen/xsurface.cpp +++ b/engines/xeen/xsurface.cpp @@ -28,50 +28,4 @@ namespace Xeen { -XSurface::XSurface() : Graphics::Surface(), _freeFlag(false) { -} - -XSurface::XSurface(int width, int height) : Graphics::Surface(), - _freeFlag(false) { - create(w, h); -} - -XSurface::~XSurface() { - if (_freeFlag) - free(); -} - -void XSurface::create(uint16 width, uint16 height) { - Graphics::Surface::create(width, height, Graphics::PixelFormat::createFormatCLUT8()); - _freeFlag = true; -} - -void XSurface::create(XSurface *s, const Common::Rect &bounds) { - pixels = (byte *)s->getBasePtr(bounds.left, bounds.top); - format = Graphics::PixelFormat::createFormatCLUT8(); - pitch = s->pitch; - w = bounds.width(); - h = bounds.height(); - - _freeFlag = false; -} - -void XSurface::blitTo(XSurface &dest) const { - blitTo(dest, Common::Point()); -} - -void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const { - if (dest.getPixels() == nullptr) - dest.create(w, h); - - for (int yp = 0; yp < h; ++yp) { - const byte *srcP = (const byte *)getBasePtr(0, yp); - byte *destP = (byte *)dest.getBasePtr(destPos.x, destPos.y + yp); - - Common::copy(srcP, srcP + w, destP); - } - - dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y + h)); -} - } // End of namespace Xeen diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h index f562112e5c..40d4611419 100644 --- a/engines/xeen/xsurface.h +++ b/engines/xeen/xsurface.h @@ -26,29 +26,26 @@ #include "common/scummsys.h" #include "common/system.h" #include "common/rect.h" -#include "graphics/surface.h" +#include "graphics/managed_surface.h" namespace Xeen { -class XSurface: public Graphics::Surface { -private: - bool _freeFlag; +class BaseSurface: public Graphics::ManagedSurface { public: - virtual void addDirtyRect(const Common::Rect &r) {} + virtual void addDirtyRect(const Common::Rect &r) { + Graphics::ManagedSurface::addDirtyRect(r); + } public: - XSurface(); - XSurface(int width, int height); - virtual ~XSurface(); - - void create(uint16 width, uint16 height); - - void create(XSurface *s, const Common::Rect &bounds); - - void blitTo(XSurface &dest, const Common::Point &destPos) const; - - void blitTo(XSurface &dest) const; + BaseSurface() : Graphics::ManagedSurface() {} + BaseSurface(int width, int height) : Graphics::ManagedSurface(width, height) {} + virtual ~BaseSurface() {} +}; - bool empty() const { return getPixels() == nullptr; } +class XSurface : public BaseSurface { +public: + XSurface() : BaseSurface() {} + XSurface(int width, int height) : BaseSurface(width, height) {} + virtual ~XSurface() {} }; } // End of namespace Xeen -- cgit v1.2.3 From 1a99d8ee8d25701ad991a67d65e68d1f3d1c7f86 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 4 Sep 2016 22:01:16 -0400 Subject: XEEN: Fix compiler warnings --- engines/xeen/dialogs_party.cpp | 6 +++--- engines/xeen/dialogs_party.h | 2 +- engines/xeen/dialogs_spells.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index 18f5f3af10..a03e2d763d 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -614,7 +614,7 @@ void PartyDialog::createChar() { case Common::KEYCODE_c: { _vm->_mode = MODE_FF; bool result = saveCharacter(party._roster[freeCharList[charIndex]], - (CharacterClass)classId, race, sex, attribs); + classId, race, sex, attribs); _vm->_mode = MODE_4; if (result) @@ -966,7 +966,7 @@ int PartyDialog::exchangeAttribute(int srcAttr) { return result; } -bool PartyDialog::saveCharacter(Character &c, CharacterClass classId, +bool PartyDialog::saveCharacter(Character &c, int classId, Race race, Sex sex, uint attribs[TOTAL_ATTRIBUTES]) { if (classId == -1) { ErrorScroll::show(_vm, SELECT_CLASS_BEFORE_SAVING); @@ -997,7 +997,7 @@ bool PartyDialog::saveCharacter(Character &c, CharacterClass classId, c._xeenSide = map._loadDarkSide; c._sex = sex; c._race = race; - c._class = classId; + c._class = (CharacterClass)classId; c._level._permanent = isDarkCc ? 5 : 1; c._might._permanent = attribs[MIGHT]; diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h index 2ad2daea0d..17ec4fd300 100644 --- a/engines/xeen/dialogs_party.h +++ b/engines/xeen/dialogs_party.h @@ -100,7 +100,7 @@ private: /** * Saves the rolled character into the roster */ - bool saveCharacter(Character &c, CharacterClass classId, Race race, + bool saveCharacter(Character &c, int classId, Race race, Sex sex, uint attribs[TOTAL_ATTRIBUTES]); public: static void show(XeenEngine *vm); diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index a10dab650b..e5d8cd0f9a 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -233,7 +233,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int } else { Common::String spellName = _spells[newSelection]._name; Common::String msg = (castingCopy & 0x80) ? - Common::String::format(SPELLS_PRESS_A_KEY, msg.c_str()) : + Common::String::format(SPELLS_PRESS_A_KEY, spellName.c_str()) : Common::String::format(SPELLS_PURCHASE, spellName.c_str(), spellCost); if (Confirm::show(_vm, msg, castingCopy + 1)) { -- cgit v1.2.3 From a520a18a0101877d11cd488c5b6f93f5b63892af Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 4 Sep 2016 22:37:42 -0400 Subject: XEEN: Further fix identified warnings --- engines/xeen/dialogs_spells.cpp | 4 ++-- engines/xeen/screen.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'engines/xeen') diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index e5d8cd0f9a..e7bbbf5cbf 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -224,10 +224,10 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int break; } - warning("TODO: category -> SPELLS_ALLOWED category value"); - int spellId = _spells[newSelection]._spellId; int spellIndex = _spells[newSelection]._spellIndex; + int spellId = SPELLS_ALLOWED[category][spellIndex]; int spellCost = spells.calcSpellCost(spellId, expenseFactor); + if (isCasting) { selection = newSelection; } else { diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp index e1e7b50a56..03b751a6b9 100644 --- a/engines/xeen/screen.cpp +++ b/engines/xeen/screen.cpp @@ -29,11 +29,11 @@ namespace Xeen { -Window::Window() : _vm(nullptr), _enabled(false), _a(0), _border(0), - _xLo(0), _xHi(0), _ycL(0), _ycH(0) { +Window::Window() : XSurface(), _vm(nullptr), _enabled(false), + _a(0), _border(0), _xLo(0), _xHi(0), _ycL(0), _ycH(0) { } -Window::Window(const Window &src) : _vm(src._vm), _enabled(src._enabled), +Window::Window(const Window &src) : XSurface(), _vm(src._vm), _enabled(src._enabled), _a(src._a), _border(src._border), _xLo(src._xLo), _ycL(src._ycL), _xHi(src._xHi), _ycH(src._ycH) { if (src._vm) { @@ -43,7 +43,7 @@ Window::Window(const Window &src) : _vm(src._vm), _enabled(src._enabled), } Window::Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border, - int xLo, int ycL, int xHi, int ycH): + int xLo, int ycL, int xHi, int ycH): XSurface(), _vm(vm), _enabled(false), _a(a), _border(border), _xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) { setBounds(bounds); -- cgit v1.2.3