diff options
author | Paul Gilbert | 2018-02-20 18:50:17 -0500 |
---|---|---|
committer | Paul Gilbert | 2018-02-23 15:23:20 -0500 |
commit | 900ef91aca039dc23e4cf300070f7fa5f6f3a335 (patch) | |
tree | 3fb56a267ea2d8d3b36689eb302d44238645879e | |
parent | 1b85d1dbc966b909f9ff9c9cc0eaac4b8ab872ae (diff) | |
download | scummvm-rg350-900ef91aca039dc23e4cf300070f7fa5f6f3a335.tar.gz scummvm-rg350-900ef91aca039dc23e4cf300070f7fa5f6f3a335.tar.bz2 scummvm-rg350-900ef91aca039dc23e4cf300070f7fa5f6f3a335.zip |
XEEN: Creation of create_xeen tool
37 files changed, 5896 insertions, 2116 deletions
diff --git a/Makefile.common b/Makefile.common index 161f50f059..b296446857 100644 --- a/Makefile.common +++ b/Makefile.common @@ -308,6 +308,9 @@ endif ifdef ENABLE_MACVENTURE DIST_FILES_ENGINEDATA+=macventure.dat endif +ifdef ENABLE_XEEN +DIST_FILES_ENGINEDATA+=xeen.ccs +endif DIST_FILES_ENGINEDATA:=$(addprefix $(srcdir)/dists/engine-data/,$(DIST_FILES_ENGINEDATA)) # pred.dic is currently only used for the AGI engine diff --git a/devtools/create_project/xcode.cpp b/devtools/create_project/xcode.cpp index fb4dc5ef5b..fb459da55d 100644 --- a/devtools/create_project/xcode.cpp +++ b/devtools/create_project/xcode.cpp @@ -764,6 +764,7 @@ XcodeProvider::ValueList& XcodeProvider::getResourceFiles() const { files.push_back("dists/engine-data/toon.dat"); files.push_back("dists/engine-data/wintermute.zip"); files.push_back("dists/engine-data/macventure.dat"); + files.push_back("dists/engine-data/xeen.ccs"); files.push_back("dists/pred.dic"); files.push_back("icons/scummvm.icns"); } diff --git a/devtools/create_xeen/cc.cpp b/devtools/create_xeen/cc.cpp new file mode 100644 index 0000000000..4020301412 --- /dev/null +++ b/devtools/create_xeen/cc.cpp @@ -0,0 +1,116 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + // Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +// HACK to allow building with the SDL backend on MinGW +// see bug #1800764 "TOOLS: MinGW tools building broken" +#ifdef main +#undef main +#endif // main + +#include "cc.h" +#include "common/endian.h" + +uint16 CCArchive::convertNameToId(const Common::String &resourceName) { + if (resourceName.empty()) + return 0xffff; + + 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++) { + // Rotate the bits in 'total' right 7 places + total = (total & 0x007F) << 9 | (total & 0xFF80) >> 7; + } + + return total; +} + +void CCArchive::saveIndex() { + // Fill up the data for the index entries into a raw data block + byte *rawIndex = new byte[_index.size() * 8]; + byte b; + + byte *entryP = rawIndex; + uint entryOffset = 8 * _index.size() + 2; + for (uint i = 0; i < _index.size(); ++i, entryP += 8) { + CCEntry &entry = _index[i]; + entry._offset = entryOffset; + entryOffset += entry._size; + + WRITE_LE_UINT16(&entryP[0], entry._id); + WRITE_LE_UINT32(&entryP[2], entry._offset); + WRITE_LE_UINT16(&entryP[5], entry._size); + entryP[7] = 0; + } + + // Encrypt the index + int seed = 0xac; + for (uint i = 0; i < _index.size() * 8; ++i, seed += 0x67) { + b = (rawIndex[i] - seed) & 0xff; + b = (byte)((b >> 2) | (b << 6)); + + assert(rawIndex[i] == (byte)((((b << 2) | (b >> 6)) + seed) & 0xff)); + rawIndex[i] = b; + } + + // Write out the number of entries and the encrypted index data + _file.writeWord(_index.size()); + _file.write(rawIndex, _index.size() * 8); + + delete[] rawIndex; +} + +void CCArchive::saveEntries() { + for (uint idx = 0; idx < _index.size(); ++idx) { + CCEntry &ccEntry = _index[idx]; + + // Encrypt the entry + for (int i = 0; i < ccEntry._size; ++i) + ccEntry._data[i] ^= 0x35; + + // Write out the entry + _file.seek(ccEntry._offset); + _file.write(ccEntry._data, ccEntry._size); + } +} + +void CCArchive::close() { + saveIndex(); + saveEntries(); +} + +void CCArchive::add(const Common::String &name, Common::MemFile &f) { + _index.push_back(CCEntry(convertNameToId(name), f.getData(), f.size())); +} diff --git a/devtools/create_xeen/cc.h b/devtools/create_xeen/cc.h new file mode 100644 index 0000000000..192a7d5c37 --- /dev/null +++ b/devtools/create_xeen/cc.h @@ -0,0 +1,84 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 CC_H +#define CC_H + +#include "file.h" +#include "str.h" +#include "common/array.h" + +/** + * Details of a single entry in a CC file index + */ +struct CCEntry { + uint16 _id; + int _offset; + uint16 _size; + byte _data[MAX_MEM_SIZE]; + + CCEntry() : _id(0), _offset(0), _size(0) { + memset(_data, 0, MAX_MEM_SIZE); + } + CCEntry(uint16 id, const byte *data, uint32 size) : + _id(id), _offset(0), _size(size) { + memcpy(_data, data, size); + } +}; + +class CCArchive { +private: + Common::Array<CCEntry> _index; + Common::File &_file; +private: + /** + * Convert a resource name to it's equivalent hash key + */ + uint16 convertNameToId(const Common::String &resourceName); + + /** + * Saves the index to the file + */ + void saveIndex(); + + /** + * Saves the individual entries to the file + */ + void saveEntries(); +public: + /** + * Constructor + */ + CCArchive(Common::File &file) : _file(file) {} + + /** + * Finishes the CC file, writing out the resulting content + */ + void close(); + + /** + * Adds an entry to the CC + */ + void add(const Common::String &name, Common::MemFile &f); +}; + +#endif diff --git a/devtools/create_xeen/constants.cpp b/devtools/create_xeen/constants.cpp new file mode 100644 index 0000000000..a74455822d --- /dev/null +++ b/devtools/create_xeen/constants.cpp @@ -0,0 +1,2098 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + // Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +// HACK to allow building with the SDL backend on MinGW +// see bug #1800764 "TOOLS: MinGW tools building broken" +#ifdef main +#undef main +#endif // main + +#include "file.h" +#include "constants.h" + +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 +}; + +const char *const CREDITS = + "\013""012\010""000\003""c\014""35Designed and Directed By:\n" + "\014""17Jon Van Caneghem\003""l\n" + "\n" + "\t025\014""35Programming:\n" + "\t035\014""17Mark Caldwell\n" + "\t035Dave Hathaway\n" + "\n" + "\t025\014""35Sound System & FX:\n" + "\t035\014""17Mike Heilemann\n" + "\n" + "\t025\014""35Music & Speech:\n" + "\t035\014""17Tim Tully\n" + "\n" + "\t025\014""35Writing:\n" + "\t035\014""17Paul Rattner\n" + "\t035Debbie Van Caneghem\n" + "\t035Jon Van Caneghem\013""012\n" + "\n" + "\n" + "\t180\014""35Graphics:\n" + "\t190\014""17Jonathan P. Gwyn\n" + "\t190Bonita Long-Hemsath\n" + "\t190Julia Ulano\n" + "\t190Ricardo Barrera\n" + "\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\003""c"; + +const char *const OPTIONS_TITLE = + "\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"; + +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 HOW_MUCH = "\x3""cHow Much\n\n"; + +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" +}; + +const char *const OUTDOORS_WALL_TYPES[16] = { + nullptr, "mount", "ltree", "dtree", "grass", "snotree", "dsnotree", + "snomnt", "dedltree", "mount", "lavamnt", "palm", "dmount", "dedltree", + "dedltree", "dedltree" +}; + +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", + "space.srf" +}; + +const char *const WHO_ACTIONS[32] = { + "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] = { + "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, + 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 }, +}; + +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" }; + +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" }; + +const char *const SKILL_NAMES[18] = { + "Thievery\t100", "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 +}; + +const int CLASS_EXP_LEVELS[10] = { + 1500, 2000, 2000, 1500, 2000, 1000, 1500, 1500, 1500, 2000 +}; + +const char *const CONDITION_NAMES[17] = { + "Cursed", "Heart Broken", "Weak", "Poisoned", "Diseased", + "Insane", "In Love", "Drunk", "Asleep", "Depressed", "Confused", + "Paralyzed", "Unconscious", "Dead", "Stone", "Eradicated", "Good" +}; + +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" + "\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 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 +}; + +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 DARKNESS_XLAT[3][256] = { + { + 0, 25, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 60, 61, 62, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 76, 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 108, 109, 110, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 124, 125, 126, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 140, 141, 142, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 168, 169, 170, 171, 172, 173, 174, 175, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 188, 189, 190, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 204, 205, 206, 207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 220, 221, 222, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 236, 237, 238, 239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 252, 253, 254, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, { + 0, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, + 56, 57, 58, 59, 60, 61, 62, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 72, 73, 74, 75, 76, 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, + 88, 89, 90, 91, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, + 104, 105, 106, 107, 108, 109, 110, 111, 0, 0, 0, 0, 0, 0, 0, 0, + 120, 121, 122, 123, 124, 125, 126, 127, 0, 0, 0, 0, 0, 0, 0, 0, + 136, 137, 138, 139, 140, 141, 142, 143, 0, 0, 0, 0, 0, 0, 0, 0, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 184, 185, 186, 187, 188, 189, 190, 191, 0, 0, 0, 0, 0, 0, 0, 0, + 200, 201, 202, 203, 204, 205, 206, 207, 0, 0, 0, 0, 0, 0, 0, 0, + 216, 217, 218, 219, 220, 221, 222, 223, 0, 0, 0, 0, 0, 0, 0, 0, + 232, 233, 234, 235, 236, 237, 238, 239, 0, 0, 0, 0, 0, 0, 0, 0, + 248, 249, 250, 251, 252, 253, 254, 255, 0, 0, 0, 0, 0, 0, 0, 0 + }, { + 0, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 0, 0, 0, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 0, 0, 0, 0, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 0, 0, 0, 0, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 0, 0, 0, 0, + 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 0, 0, 0, 0, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 0, 0, 0, 0, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 174, 175, 0, 0, 0, 0, 0, 0, 0, 0, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 0, 0, 0, 0, + 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 0, 0, 0, 0, + 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 0, 0, 0, 0, + 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 0, 0, 0, 0, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 0, 0, 0, 0 + } +}; + +const char *const PLEASE_WAIT = "\014""d\003""c\011""000" + "\013""002Please Wait..."; + +const char *const OOPS = "\003""c\011""000\013""002Oops..."; + +const int 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 int 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 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 } +}; + +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 } +}; + +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_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] = { + { 0, 1, 2, 3 }, { 3, 0, 1, 2 }, { 2, 3, 0, 1 }, { 1, 2, 3, 0 } +}; + +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, + 0, 12, 0, 12, 8, 12, 8, 12, 8, 12, 8, 12, + 0, 0, 0, 0, 8, 8, 8, 8, 0, 0, 4, 4 + }, { + 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 + }, { + 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, 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 + } +}; + +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 }, { 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 } +}; + +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 } +}; + +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 + } +}; + +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] = { + 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 25, 30, 35, 40, + 50, 75, 100, 125, 150, 175, 200, 225, 250, +}; + +const int STAT_BONUSES[24] = { + -5, -4, -3, -2, -1, 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 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 }; + +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_DRAWSTRUCT_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 +}; + +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[2][7] = { + { "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[7] = { + "bnkr", "blck", "gild", "tvrn", "tmpl", "trng", "eface08" +}; + +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 = "\xD\x2\x3""c\xB""122\t013" + "\xC""37D\xC""dep\t040\xC""37W\xC""dith\t067ESC" + "\x1\t000\xB""000Bank of Xeen\xB""015\n" + "Bank\x3l\n" + "Gold\x3r\t000%s\x3l\n" + "Gems\x3r\t000%s\x3""c\n" + "\n" + "Party\x3l\n" + "Gold\x3r\t000%s\x3l\n" + "Gems\x3r\t000%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 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" + "\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"; + +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 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 = + "\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"; + +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 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, + 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 +}; + +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 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" +}; + +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"; + +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"; + +const int BLACKSMITH_MAP_IDS[2][4] = { { 28, 30, 73, 49 }, { 29, 31, 37, 43 } }; + +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"; +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"; +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"; + +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 ", "sale armor ", "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", + "bogusg", "bogus", "bogus", "bogus", "bogus", + "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 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)", + "", + "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, + 300, 100, 200, 300, 25, 100, 50, 15, 0 +}; +const int ARMOR_BASE_COSTS[14] = { + 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 }; + +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!"; + +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\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 = "\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!"; +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!"; + +const char *const PERMANENTLY_DISCARD = "\v000\t000\x03lPermanently discard %s\fd?"; + +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.", + "\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?"; + +const char *const NO_NEED_OF_THIS = "\v005\x3""c\fdWe have no need of this %s\f!"; + +const char *const NOT_RECHARGABLE = "\v012\x3""c\fdNot Rechargeable. %s"; + +const char *const NOT_ENCHANTABLE = "\v012\t000\x3""cNot 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"; + +const char *const QUESTS_DIALOG_TEXT = + "\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 = + "\r\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"; + +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?"; + +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!"; + +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?"; + +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 char *const NAME_FOR_NEW_CHARACTER = + "\x3""cEnter a Name for this Character\n\n"; +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 }; + +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 } +}; + +const char *const COMBAT_DETAILS = "\r\f00\x3""c\v000\t000\x2""Combat%s%s%s\x1"; + +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 = + "\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"; + +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\xC""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\x3""c%s found: %s"; + +const char *const ON_WHO = "\x3""c\v009On Who?"; + +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"; + +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"; + +const char *const HOW_MANY_SQUARES = "\x3""cTeleport\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 } +}; + +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"; + +const char *const EVENT_SAMPLES[6] = { + "ahh.voc", "whereto.voc", "gulp.voc", "null.voc", "scream.voc", "laff1.voc" +}; + +const char *const MOONS_NOT_ALIGNED = +"\x3""c\xB""012\t000The moons are not aligned. Passage to the %s is unavailable"; + +const char *const AWARDS_FOR = + "\r\x1\fd\x3""c\v000\t000Awards for %s the %s\x3""l\x2\n" + "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\x1"; + +const char *const AWARDS_TEXT = + "\r\x2\x3""c\xB""021\t221\xC""37U\xC""dp\t255\xC""37D\xC""down\t289Exit"; + +const char *const NO_AWARDS = "\x3""cNo Awards"; + +const char *const WARZONE_BATTLE_MASTER = "The Warzone\n\t125Battle Master"; + +const char *const WARZONE_MAXED = "What! You again? Go pick on someone your own size!"; + +const char *const WARZONE_LEVEL = "What level of monsters? (1-10)\n"; + +const char *const WARZONE_HOW_MANY = "How many monsters? (1-20)\n"; + +const char *const PICKS_THE_LOCK = "\x3""c\xB""010%s picks the lock!\nPress any key."; + +const char *const UNABLE_TO_PICK_LOCK = "\x3""c\v010%s was unable to pick the lock!\nPress any key."; + +const char *const CONTROL_PANEL_TEXT = + "\x1\xC""00\x3""c\xB""000\t000Control Panel\x3r" + "\xB""022\t045\xC""06L\xC""doad:\t124\xC""06E\xC""dfx:" + "\xB""041\t045\xC""06S\xC""dave:\t124\xC""06M\xC""dusic:" + "\xB""060\t045\xC""06Q\xC""duit:" + "\xB""080\t084Mr \xC""06W\xC""dizard:%s\t000\x1"; +const char *const CONTROL_PANEL_BUTTONS = + "\x3""c\f11" + "\xB""022\t062load\t141%s" + "\xB""041\t062save\t141%s" + "\xB""060\t062exit" + "\xB""079\t102Help\xC""d"; +const char *const ON = "\f15on\f11"; +const char *const OFF = "\f32off\f11"; +const char *const CONFIRM_QUIT = "Are you sure you want to quit?"; +const char *const MR_WIZARD = + "Are you sure you want Mr.Wizard's Help ?"; +const char *const NO_LOADING_IN_COMBAT = + "No Loading Allowed in Combat!"; +const char *const NO_SAVING_IN_COMBAT = + "No Saving Allowed in Combat!"; +const char *const QUICK_FIGHT_TEXT = "\r\fd\x3""c\v000\t000QuickFight Options\n\n" + "%s\x3l\n\n" + "Current\x3r\n" + "\t000%s\x2\x3""c\v122\t021\f37N\f04ext\t060Exit\x1"; +const char *const QUICK_FIGHT_OPTIONS[4] = { "Attack", "Cast", "Block", "Run" }; + +const char *const WORLD_END_TEXT[9] = { + "\n\n\n\n\n\n\n" + "Congratulations Adventurers!\n\n" + "Let the unification ceremony begin!", + "And so the call went out to the people throughout the lands of Xeen" + " that the prophecy was nearing completion.", + "They came in great numbers to witness the momentous occasion.", + "\xB""026The Dragon Pharoah presided over the ceremony.", + "\xB""026Queen Kalindra presented the Cube of Power.", + "\xB""026Prince Roland presented the Xeen Sceptre.", + "\xB""026Together, they placed the Cube of Power...", + "\xB""026and the Sceptre, onto the Altar of Joining.", + "With the prophecy complete, the two sides of Xeen were united as one", +}; + +const char *const WORLD_CONGRATULATIONS = + "\x3""cCongratulations\n\n" + "Your Final Score is:\n\n" + "%010lu\n" + "\x3l\n" + "Please send this score to the Ancient's Headquarters where " + "you'll be added to the Hall of Legends!\n\n" + "Ancient's Headquarters\n" + "New World Computing, Inc.\n" + "P.O. Box 4302\n" + "Hollywood, CA 90078"; +const char *const WORLD_CONGRATULATIONS2 = + "\n\n\n\n\n\n" + "But wait... there's more!\n" + "\n\n" + "Include the message\n" + "\"%s\"\n" + "with your final score and receive a special bonus."; +const char *const CLOUDS_CONGRATULATIONS1 = + "\xC""23\x3l" + "\xB""000\t000Please send this score to the Ancient's Headquarters " + "where you'll be added to the Hall of Legends!\xC""33\x3""c" + "\xB""070\t000Press a Key"; +const char *const CLOUDS_CONGRATULATIONS2 = + "\xC""23\x3l" + "\xB""000\t000Ancient's Headquarters\n" + "New World Computing, Inc.\n" + "P.O. Box 4302\n" + "Hollywood, CA 90078-4302\xC""33\x3""c" + "\xB""070\t000Press a Key"; +const char *const GOOBER[3] = { + "", "I am a Goober!", "I am a Super Goober!" +}; + +const char *const MUSIC_FILES1[5] = { + "outdoors.m", "town.m", "cavern.m", "dungeon.m", "castle.m" +}; + +const char *const MUSIC_FILES2[6][7] = { + { "outday1.m", "outday2.m", "outday4.m", "outnght1.m", + "outnght2.m", "outnght4.m", "daydesrt.m" }, + { "townday1.m", "twnwlk.m", "newbrigh.m", "twnnitea.m", + "twnniteb.m", "twnwlk.m", "townday1.m" }, + { "cavern1.m", "cavern2.m", "cavern3a.m", "cavern1.m", + "cavern2.m", "cavern3a.m", "cavern1.m" }, + { "dngon1.m", "dngon2.m", "dngon3.m", "dngon1.m", + "dngon2.m", "dngon3.m", "dngon1.m" }, + { "cstl1rev.m", "cstl2rev.m", "cstl3rev.m", "cstl1rev.m", + "cstl2rev.m", "cstl3rev.m", "cstl1rev.m" }, + { "sf05.m", "sf05.m", "sf05.m", "sf05.m", "sf05.m", "sf05.m", "sf05.m" } +}; + +void writeConstants(CCArchive &cc) { + Common::MemFile file; + file.syncString(CREDITS); + file.syncString(OPTIONS_TITLE); + file.syncString(THE_PARTY_NEEDS_REST); + file.syncString(WHO_WILL); + file.syncString(HOW_MUCH); + file.syncString(WHATS_THE_PASSWORD); + file.syncString(IN_NO_CONDITION); + file.syncString(NOTHING_HERE); + file.syncStrings(TERRAIN_TYPES, 6); + file.syncStrings(OUTDOORS_WALL_TYPES, 16); + file.syncStrings(SURFACE_NAMES, 16); + file.syncStrings(WHO_ACTIONS, 32); + file.syncStrings(WHO_WILL_ACTIONS, 4); + file.syncBytes2D((const byte *)SYMBOLS, 20, 64); + file.syncBytes2D((const byte *)TEXT_COLORS, 40, 4); + file.syncStrings(DIRECTION_TEXT_UPPER, 4); + file.syncStrings(DIRECTION_TEXT, 4); + file.syncStrings(RACE_NAMES, 5); + file.syncNumbers(RACE_HP_BONUSES, 5); + file.syncNumbers2D((const int *)RACE_SP_BONUSES, 5, 2); + file.syncStrings(CLASS_NAMES, 11); + file.syncNumbers(CLASS_EXP_LEVELS, 10); + file.syncStrings(ALIGNMENT_NAMES, 3); + file.syncStrings(SEX_NAMES, 2); + file.syncStrings(SKILL_NAMES, 18); + file.syncStrings(CONDITION_NAMES, 17); + file.syncNumbers(CONDITION_COLORS, 17); + file.syncString(GOOD); + file.syncString(BLESSED); + file.syncString(POWER_SHIELD); + file.syncString(HOLY_BONUS); + file.syncString(HEROISM); + file.syncString(IN_PARTY); + file.syncString(PARTY_DETAILS); + file.syncString(PARTY_DIALOG_TEXT); + file.syncNumbers(FACE_CONDITION_FRAMES, 17); + file.syncNumbers(CHAR_FACES_X, 6); + file.syncNumbers(HP_BARS_X, 6); + file.syncString(NO_ONE_TO_ADVENTURE_WITH); + file.syncBytes2D((const byte *)DARKNESS_XLAT, 3, 256); + file.syncString(YOUR_ROSTER_IS_FULL); + file.syncString(PLEASE_WAIT); + file.syncString(OOPS); + file.syncNumbers2D((const int *)SCREEN_POSITIONING_X, 4, 48); + file.syncNumbers2D((const int *)SCREEN_POSITIONING_Y, 4, 48); + file.syncNumbers(MONSTER_GRID_BITMASK, 12); + file.syncNumbers2D((const int *)INDOOR_OBJECT_X, 2, 12); + file.syncNumbers2D((const int *)MAP_OBJECT_Y, 2, 12); + file.syncNumbers(INDOOR_MONSTERS_Y, 4); + file.syncNumbers2D((const int *)OUTDOOR_OBJECT_X, 2, 12); + file.syncNumbers(OUTDOOR_MONSTER_INDEXES, 26); + file.syncNumbers(OUTDOOR_MONSTERS_Y, 26); + file.syncNumbers2D((const int *)DIRECTION_ANIM_POSITIONS, 4, 4); + file.syncBytes2D((const byte *)WALL_SHIFTS, 4, 48); + file.syncNumbers(DRAW_NUMBERS, 25); + file.syncNumbers2D((const int *)DRAW_FRAMES, 25, 2); + file.syncNumbers(COMBAT_FLOAT_X, 8); + file.syncNumbers(COMBAT_FLOAT_Y, 8); + file.syncNumbers2D((const int *)MONSTER_EFFECT_FLAGS, 15, 8); + file.syncNumbers2D((const int *)SPELLS_ALLOWED, 3, 40); + file.syncNumbers(BASE_HP_BY_CLASS, 10); + file.syncNumbers(AGE_RANGES, 10); + file.syncNumbers2D((const int *)AGE_RANGES_ADJUST, 2, 10); + file.syncNumbers(STAT_VALUES, 24); + file.syncNumbers(STAT_BONUSES, 24); + file.syncNumbers(ELEMENTAL_CATEGORIES, 6); + file.syncNumbers(ATTRIBUTE_CATEGORIES, 10); + file.syncNumbers(ATTRIBUTE_BONUSES, 72); + file.syncNumbers(ELEMENTAL_RESISTENCES, 37); + file.syncNumbers(ELEMENTAL_DAMAGE, 37); + file.syncNumbers(WEAPON_DAMAGE_BASE, 35); + file.syncNumbers(WEAPON_DAMAGE_MULTIPLIER, 35); + file.syncNumbers(METAL_DAMAGE, 22); + file.syncNumbers(METAL_DAMAGE_PERCENT, 22); + file.syncNumbers(METAL_LAC, 9); + file.syncNumbers(ARMOR_STRENGTHS, 14); + file.syncNumbers(MAKE_ITEM_ARR1, 6); + file.syncNumbers3D((const int *)MAKE_ITEM_ARR2, 6, 7, 2); + file.syncNumbers3D((const int *)MAKE_ITEM_ARR3, 10, 7, 2); + file.syncNumbers3D((const int *)MAKE_ITEM_ARR4, 2, 7, 2); + file.syncNumbers2D((const int *)MAKE_ITEM_ARR5, 8, 2); + file.syncNumbers(OUTDOOR_DRAWSTRUCT_INDEXES, 44); + file.syncNumbers2D((const int *)TOWN_MAXES, 2, 11); + file.syncStrings2D((const char *const *)TOWN_ACTION_MUSIC, 2, 7); + file.syncStrings(TOWN_ACTION_SHAPES, 7); + file.syncNumbers2D((const int *)TOWN_ACTION_FILES, 2, 7); + file.syncString(BANK_TEXT); + file.syncString(BLACKSMITH_TEXT); + file.syncString(GUILD_NOT_MEMBER_TEXT); + file.syncString(GUILD_TEXT); + file.syncString(TAVERN_TEXT); + file.syncString(GOOD_STUFF); + file.syncString(HAVE_A_DRINK); + file.syncString(YOURE_DRUNK); + file.syncNumbers4D((const int *)TAVERN_EXIT_LIST, 2, 6, 5, 2); + file.syncString(FOOD_AND_DRINK); + file.syncString(TEMPLE_TEXT); + file.syncString(EXPERIENCE_FOR_LEVEL); + file.syncString(LEARNED_ALL); + file.syncString(ELIGIBLE_FOR_LEVEL); + file.syncString(TRAINING_TEXT); + file.syncString(GOLD_GEMS); + file.syncString(GOLD_GEMS_2); + file.syncString(DEPOSIT_WITHDRAWL[2]); + file.syncString(NOT_ENOUGH_X_IN_THE_Y); + file.syncString(NO_X_IN_THE_Y); + file.syncString(STAT_NAMES[16]); + file.syncString(CONSUMABLE_NAMES[4]); + file.syncString(WHERE_NAMES[2]); + file.syncString(AMOUNT); + file.syncString(FOOD_PACKS_FULL); + file.syncString(BUY_SPELLS); + file.syncString(GUILD_OPTIONS); + file.syncNumbers((const int *)MISC_SPELL_INDEX, 74); + file.syncNumbers((const int *)SPELL_COSTS, 77); + file.syncNumbers2D((const int *)CLOUDS_SPELL_OFFSETS, 5, 20); + file.syncNumbers2D((const int *)DARK_SPELL_OFFSETS, 3, 39); + file.syncNumbers2D((const int *)DARK_SPELL_RANGES, 12, 2); + file.syncNumbers((const int *)SPELL_GEM_COST, 77); + file.syncString(NOT_A_SPELL_CASTER); + file.syncString(SPELLS_FOR); + file.syncString(SPELL_LINES_0_TO_9); + file.syncString(SPELLS_DIALOG_SPELLS); + file.syncString(SPELL_PTS); + file.syncString(GOLD); + file.syncString(SPELLS_PRESS_A_KEY); + file.syncString(SPELLS_PURCHASE); + file.syncString(MAP_TEXT); + file.syncString(LIGHT_COUNT_TEXT); + file.syncString(FIRE_RESISTENCE_TEXT); + file.syncString(ELECRICITY_RESISTENCE_TEXT); + file.syncString(COLD_RESISTENCE_TEXT); + file.syncString(POISON_RESISTENCE_TEXT); + file.syncString(CLAIRVOYANCE_TEXT); + file.syncString(LEVITATE_TEXT); + file.syncString(WALK_ON_WATER_TEXT); + file.syncString(GAME_INFORMATION); + file.syncString(WORLD_GAME_TEXT); + file.syncString(DARKSIDE_GAME_TEXT); + file.syncString(CLOUDS_GAME_TEXT); + file.syncString(SWORDS_GAME_TEXT); + file.syncStrings(WEEK_DAY_STRINGS, 10); + file.syncString(CHARACTER_DETAILS); + file.syncString(PARTY_GOLD); + file.syncString(PLUS_14); + file.syncString(CHARACTER_TEMPLATE); + file.syncString(EXCHANGING_IN_COMBAT); + file.syncString(CURRENT_MAXIMUM_RATING_TEXT); + file.syncString(CURRENT_MAXIMUM_TEXT); + file.syncStrings(RATING_TEXT, 24); + file.syncString(AGE_TEXT); + file.syncString(LEVEL_TEXT); + file.syncString(RESISTENCES_TEXT); + file.syncString(NONE); + file.syncString(EXPERIENCE_TEXT); + file.syncString(ELIGIBLE); + file.syncString(IN_PARTY_IN_BANK); + file.syncString(FOOD_TEXT); + file.syncString(EXCHANGE_WITH_WHOM); + file.syncString(QUICK_REF_LINE); + file.syncString(QUICK_REFERENCE); + file.syncNumbers2D((const int *)BLACKSMITH_MAP_IDS, 2, 4); + file.syncString(ITEMS_DIALOG_TEXT1); + file.syncString(ITEMS_DIALOG_TEXT2); + file.syncString(ITEMS_DIALOG_LINE1); + file.syncString(ITEMS_DIALOG_LINE2); + file.syncString(BTN_BUY); + file.syncString(BTN_SELL); + file.syncString(BTN_IDENTIFY); + file.syncString(BTN_FIX); + file.syncString(BTN_USE); + file.syncString(BTN_EQUIP); + file.syncString(BTN_REMOVE); + file.syncString(BTN_DISCARD); + file.syncString(BTN_QUEST); + file.syncString(BTN_ENCHANT); + file.syncString(BTN_RECHARGE); + file.syncString(BTN_GOLD); + file.syncString(ITEM_BROKEN); + file.syncString(ITEM_CURSED); + file.syncStrings(BONUS_NAMES, 7); + file.syncStrings(WEAPON_NAMES, 35); + file.syncStrings(ARMOR_NAMES, 14); + file.syncStrings(ACCESSORY_NAMES, 11); + file.syncStrings(MISC_NAMES, 22); + file.syncStrings(ELEMENTAL_NAMES, 6); + file.syncStrings(ATTRIBUTE_NAMES, 10); + file.syncStrings(EFFECTIVENESS_NAMES, 7); + file.syncStrings(QUEST_ITEM_NAMES, 85); + file.syncNumbers((const int *)WEAPON_BASE_COSTS, 35); + file.syncNumbers((const int *)ARMOR_BASE_COSTS, 14); + file.syncNumbers((const int *)ACCESSORY_BASE_COSTS, 11); + file.syncNumbers((const int *)MISC_MATERIAL_COSTS, 22); + file.syncNumbers((const int *)MISC_BASE_COSTS, 76); + file.syncNumbers((const int *)METAL_BASE_MULTIPLIERS, 22); + file.syncNumbers((const int *)ITEM_SKILL_DIVISORS, 4); + file.syncNumbers((const int *)RESTRICTION_OFFSETS, 4); + file.syncNumbers((const int *)ITEM_RESTRICTIONS, 86); + file.syncString(NOT_PROFICIENT); + file.syncString(NO_ITEMS_AVAILABLE); + file.syncStrings(CATEGORY_NAMES, 4); + file.syncString(X_FOR_THE_Y); + file.syncString(X_FOR_Y); + file.syncString(X_FOR_Y_GOLD); + file.syncString(FMT_CHARGES); + file.syncString(AVAILABLE_GOLD_COST); + file.syncString(CHARGES); + file.syncString(COST); + file.syncStrings(ITEM_ACTIONS, 7); + file.syncString(WHICH_ITEM); + file.syncString(WHATS_YOUR_HURRY); + file.syncString(USE_ITEM_IN_COMBAT); + file.syncString(NO_SPECIAL_ABILITIES); + file.syncString(CANT_CAST_WHILE_ENGAGED); + file.syncString(EQUIPPED_ALL_YOU_CAN); + file.syncString(REMOVE_X_TO_EQUIP_Y); + file.syncString(RING); + file.syncString(MEDAL); + file.syncString(CANNOT_REMOVE_CURSED_ITEM); + file.syncString(CANNOT_DISCARD_CURSED_ITEM); + file.syncString(PERMANENTLY_DISCARD); + file.syncString(BACKPACK_IS_FULL); + file.syncStrings(CATEGORY_BACKPACK_IS_FULL, 4); + file.syncString(BUY_X_FOR_Y_GOLD); + file.syncString(SELL_X_FOR_Y_GOLD); + file.syncString(NO_NEED_OF_THIS); + file.syncString(NOT_RECHARGABLE); + file.syncString(SPELL_FAILED); + file.syncString(NOT_ENCHANTABLE); + file.syncString(ITEM_NOT_BROKEN); + file.syncStrings(FIX_IDENTIFY, 2); + file.syncString(FIX_IDENTIFY_GOLD); + file.syncString(IDENTIFY_ITEM_MSG); + file.syncString(ITEM_DETAILS); + file.syncString(ALL); + file.syncString(FIELD_NONE); + file.syncString(DAMAGE_X_TO_Y); + file.syncString(ELEMENTAL_XY_DAMAGE); + file.syncString(ATTR_XY_BONUS); + file.syncString(EFFECTIVE_AGAINST); + file.syncString(QUESTS_DIALOG_TEXT); + file.syncString(CLOUDS_OF_XEEN_LINE); + file.syncString(DARKSIDE_OF_XEEN_LINE); + file.syncString(NO_QUEST_ITEMS); + file.syncString(NO_CURRENT_QUESTS); + file.syncString(NO_AUTO_NOTES); + file.syncString(QUEST_ITEMS_DATA); + file.syncString(CURRENT_QUESTS_DATA); + file.syncString(AUTO_NOTES_DATA); + file.syncString(REST_COMPLETE); + file.syncString(PARTY_IS_STARVING); + file.syncString(HIT_SPELL_POINTS_RESTORED); + file.syncString(TOO_DANGEROUS_TO_REST); + file.syncString(SOME_CHARS_MAY_DIE); + file.syncString(CANT_DISMISS_LAST_CHAR); + file.syncStrings(REMOVE_DELETE, 2); + file.syncString(REMOVE_OR_DELETE_WHICH); + file.syncString(YOUR_PARTY_IS_FULL); + file.syncString(HAS_SLAYER_SWORD); + file.syncString(SURE_TO_DELETE_CHAR); + file.syncString(CREATE_CHAR_DETAILS); + file.syncString(NEW_CHAR_STATS); + file.syncString(NAME_FOR_NEW_CHARACTER); + file.syncString(SELECT_CLASS_BEFORE_SAVING); + file.syncString(EXCHANGE_ATTR_WITH); + file.syncNumbers((const int *)NEW_CHAR_SKILLS, 10); + file.syncNumbers((const int *)NEW_CHAR_SKILLS_LEN, 10); + file.syncNumbers((const int *)NEW_CHAR_RACE_SKILLS, 10); + file.syncNumbers((const int *)RACE_MAGIC_RESISTENCES, 5); + file.syncNumbers((const int *)RACE_FIRE_RESISTENCES, 5); + file.syncNumbers((const int *)RACE_ELECTRIC_RESISTENCES, 5); + file.syncNumbers((const int *)RACE_COLD_RESISTENCES, 5); + file.syncNumbers((const int *)RACE_ENERGY_RESISTENCES, 5); + file.syncNumbers((const int *)RACE_POISON_RESISTENCES, 5); + file.syncNumbers2D((const int *)NEW_CHARACTER_SPELLS, 10, 4); + file.syncString(COMBAT_DETAILS); + file.syncString(NOT_ENOUGH_TO_CAST); + file.syncStrings(SPELL_CAST_COMPONENTS, 2); + file.syncString(CAST_SPELL_DETAILS); + file.syncString(PARTY_FOUND); + file.syncString(BACKPACKS_FULL_PRESS_KEY); + file.syncString(HIT_A_KEY); + file.syncString(GIVE_TREASURE_FORMATTING); + file.syncString(X_FOUND_Y); + file.syncString(ON_WHO); + file.syncString(WHICH_ELEMENT1); + file.syncString(WHICH_ELEMENT2); + file.syncString(DETECT_MONSTERS); + file.syncString(LLOYDS_BEACON); + file.syncString(HOW_MANY_SQUARES); + file.syncString(TOWN_PORTAL); + file.syncNumbers2D((const int *)TOWN_MAP_NUMBERS, 2, 5); + file.syncString(MONSTER_DETAILS); + file.syncStrings(MONSTER_SPECIAL_ATTACKS, 23); + file.syncString(IDENTIFY_MONSTERS); + file.syncStrings(EVENT_SAMPLES, 6); + file.syncString(MOONS_NOT_ALIGNED); + file.syncString(AWARDS_FOR); + file.syncString(AWARDS_TEXT); + file.syncString(NO_AWARDS); + file.syncString(WARZONE_BATTLE_MASTER); + file.syncString(WARZONE_MAXED); + file.syncString(WARZONE_LEVEL); + file.syncString(WARZONE_HOW_MANY); + file.syncString(PICKS_THE_LOCK); + file.syncString(UNABLE_TO_PICK_LOCK); + file.syncString(CONTROL_PANEL_TEXT); + file.syncString(CONTROL_PANEL_BUTTONS); + file.syncString(ON); + file.syncString(OFF); + file.syncString(CONFIRM_QUIT); + file.syncString(MR_WIZARD); + file.syncString(NO_LOADING_IN_COMBAT); + file.syncString(NO_SAVING_IN_COMBAT); + file.syncString(QUICK_FIGHT_TEXT); + file.syncStrings(QUICK_FIGHT_OPTIONS, 4); + file.syncStrings(WORLD_END_TEXT, 9); + file.syncString(WORLD_CONGRATULATIONS); + file.syncString(WORLD_CONGRATULATIONS2); + file.syncString(CLOUDS_CONGRATULATIONS1); + file.syncString(CLOUDS_CONGRATULATIONS2); + file.syncStrings(GOOBER, 3); + file.syncStrings(MUSIC_FILES1, 5); + file.syncStrings2D((const char *const *)MUSIC_FILES2, 6, 7); + + cc.add("CONSTANTS", file); +} diff --git a/devtools/create_xeen/constants.h b/devtools/create_xeen/constants.h new file mode 100644 index 0000000000..32177e80ac --- /dev/null +++ b/devtools/create_xeen/constants.h @@ -0,0 +1,31 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 CONSTANTS_H +#define CONSTANTS_H + +#include "common/scummsys.h" +#include "cc.h" + +extern void writeConstants(CCArchive &cc); + +#endif diff --git a/devtools/create_xeen/create_xeen.cpp b/devtools/create_xeen/create_xeen.cpp new file mode 100644 index 0000000000..94af74f517 --- /dev/null +++ b/devtools/create_xeen/create_xeen.cpp @@ -0,0 +1,65 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + // Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +// HACK to allow building with the SDL backend on MinGW +// see bug #1800764 "TOOLS: MinGW tools building broken" +#ifdef main +#undef main +#endif // main + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "cc.h" +#include "file.h" +#include "constants.h" + +#define VERSION_NUMBER 1 + +Common::File outputFile; + +void NORETURN_PRE error(const char *s, ...) { + printf("%s\n", s); + exit(1); +} + +void writeVersion(CCArchive &cc) { + Common::MemFile f; + f.writeLong(VERSION_NUMBER); + cc.add("VERSION", f); +} + +int main(int argc, char *argv[]) { + if (!outputFile.open(argc == 1 ? "xeen.ccs" : argv[1], Common::kFileWriteMode)) { + error("Could not open input file"); + } + + CCArchive cc(outputFile); + writeVersion(cc); + writeConstants(cc); + + cc.close(); + return 0; +} diff --git a/devtools/create_xeen/file.h b/devtools/create_xeen/file.h new file mode 100644 index 0000000000..8fdb9b44a9 --- /dev/null +++ b/devtools/create_xeen/file.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 __FILE_H__ +#define __FILE_H__ + +#include <stdio.h> +#include <stdlib.h> + +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "common/scummsys.h" +#include "common/endian.h" +#include "common/util.h" + +namespace Common { + +enum AccessMode { + kFileReadMode = 1, + kFileWriteMode = 2 +}; + +class Stream { +public: + Stream() {} + virtual ~Stream() {} + + virtual int seek(int offset, int whence = SEEK_SET) = 0; + virtual long read(void *buffer, size_t len) = 0; + virtual void write(const void *buffer, size_t len) = 0; + virtual uint pos() const = 0; + virtual uint size() const = 0; + virtual bool eof() const = 0; + + void skip(int offset) { + seek(offset, SEEK_CUR); + } + void write(Stream &src, size_t len) { + for (size_t idx = 0; idx < len; ++idx) + writeByte(src.readByte()); + } + byte readByte() { + byte v; + read(&v, sizeof(byte)); + return v; + } + uint16 readWord() { + uint16 v; + read(&v, sizeof(uint16)); + return FROM_LE_16(v); + } + uint readLong() { + uint v; + read(&v, sizeof(uint)); + return FROM_LE_32(v); + } + + uint readUint16BE() { + uint16 v; + read(&v, sizeof(uint16)); + return FROM_BE_16(v); + } + uint readUint16LE() { + uint16 v; + read(&v, sizeof(uint16)); + return FROM_LE_16(v); + } + uint readUint32BE() { + uint32 v; + read(&v, sizeof(uint32)); + return FROM_BE_32(v); + } + uint readUint32LE() { + uint32 v; + read(&v, sizeof(uint32)); + return FROM_LE_32(v); + } + + void writeByte(byte v) { + write(&v, sizeof(byte)); + } + void writeByte(byte v, int len) { + byte *b = new byte[len]; + memset(b, v, len); + write(b, len); + delete[] b; + } + void writeWord(uint16 v) { + uint16 vTemp = TO_LE_16(v); + write(&vTemp, sizeof(uint16)); + } + void writeLong(uint v) { + uint vTemp = TO_LE_32(v); + write(&vTemp, sizeof(uint)); + } + void writeString(const char *msg) { + if (!msg) { + writeByte(0); + } + else { + do { + writeByte(*msg); + } while (*msg++); + } + } +}; + +class File : public Stream { +private: + ::FILE *_f; +public: + File() : _f(nullptr) {} + virtual ~File() { close(); } + + bool open(const char *filename, AccessMode mode = kFileReadMode) { + _f = fopen(filename, (mode == kFileReadMode) ? "rb" : "wb+"); + return (_f != NULL); + } + void close() { + if (_f) + fclose(_f); + _f = nullptr; + } + + virtual int seek(int offset, int whence = SEEK_SET) { + return fseek(_f, offset, whence); + } + virtual long read(void *buffer, size_t len) { + return fread(buffer, 1, len, _f); + } + virtual void write(const void *buffer, size_t len) { + assert(_f); + fwrite(buffer, 1, len, _f); + } + virtual uint pos() const { + return ftell(_f); + } + virtual uint size() const { + uint currentPos = pos(); + fseek(_f, 0, SEEK_END); + uint result = pos(); + fseek(_f, currentPos, SEEK_SET); + return result; + } + virtual bool eof() const { + return feof(_f) != 0; + } +}; + +#define MAX_MEM_SIZE 65536 + +class MemFile : public Stream { +private: + byte _data[MAX_MEM_SIZE]; + size_t _size, _offset; +public: + MemFile() : _size(0), _offset(0) { + memset(_data, 0, MAX_MEM_SIZE); + } + virtual ~MemFile() {} + + bool open() { + memset(_data, 0, MAX_MEM_SIZE); + _size = _offset = 0; + } + void close() { + } + + virtual int seek(int offset, int whence = SEEK_SET) { + switch (whence) { + case SEEK_SET: _offset = whence; break; + case SEEK_CUR: _offset += whence; break; + case SEEK_END: _offset = _size + whence; break; + } + + return _offset; + } + virtual long read(void *buffer, size_t len) { + len = MAX(len, _size - _offset); + memcpy(buffer, &_data[_offset], len); + return len; + } + virtual void write(const void *buffer, size_t len) { + assert(len <= (MAX_MEM_SIZE - _offset)); + memcpy(&_data[_offset], buffer, len); + _offset += len; + _size = MAX(_offset, _size); + } + virtual uint pos() const { + return _offset; + } + virtual uint size() const { + return _size; + } + virtual bool eof() const { + return _offset >= _size; + } + + const byte *getData() const { return _data; } + + void syncString(const char *str) { + write(str, strlen(str) + 1); + } + void syncStrings(const char *const *str, int count) { + writeLong(MKTAG(count, 0, 0, 0)); + for (int idx = 0; idx < count; ++idx, ++str) + writeString(*str); + } + void syncStrings2D(const char *const *str, int count1, int count2) { + writeLong(MKTAG(count1, count2, 0, 0)); + for (int idx = 0; idx < count1 * count2; ++idx, ++str) + writeString(*str); + } + void syncNumber(const int val) { + writeLong(val); + } + void syncNumbers(const int *vals, int count) { + writeLong(MKTAG(count, 0, 0, 0)); + for (int idx = 0; idx < count; ++idx, ++vals) + writeLong(*vals); + } + void syncNumbers2D(const int *vals, int count1, int count2) { + writeLong(MKTAG(count1, count2, 0, 0)); + for (int idx = 0; idx < count1 * count2; ++idx, ++vals) + writeLong(*vals); + } + void syncNumbers3D(const int *vals, int count1, int count2, int count3) { + writeLong(MKTAG(count1, count2, count3, 0)); + for (int idx = 0; idx < count1 * count2 * count3; ++idx, ++vals) + writeLong(*vals); + } + void syncNumbers4D(const int *vals, int count1, int count2, int count3, int count4) { + writeLong(MKTAG(count1, count2, count3, count4)); + for (int idx = 0; idx < count1 * count2 * count3 * count4; ++idx, ++vals) + writeLong(*vals); + } + void syncBytes2D(const byte *vals, int count1, int count2) { + writeLong(MKTAG(count1, count2, 0, 0)); + write(vals, count1 * count2); + } +}; + +} // End of namespace Common + +#endif diff --git a/devtools/create_xeen/hash-str.h b/devtools/create_xeen/hash-str.h new file mode 100644 index 0000000000..b9f6d503f8 --- /dev/null +++ b/devtools/create_xeen/hash-str.h @@ -0,0 +1,86 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 COMMON_HASH_STR_H +#define COMMON_HASH_STR_H + +#include "hashmap.h" +#include "str.h" + +namespace Common { + +uint hashit(const char *str); +uint hashit_lower(const char *str); // Generate a hash based on the lowercase version of the string +inline uint hashit(const String &str) { return hashit(str.c_str()); } +inline uint hashit_lower(const String &str) { return hashit_lower(str.c_str()); } + + +// FIXME: The following functors obviously are not consistently named + +struct CaseSensitiveString_EqualTo { + bool operator()(const String& x, const String& y) const { return x.equals(y); } +}; + +struct CaseSensitiveString_Hash { + uint operator()(const String& x) const { return hashit(x.c_str()); } +}; + + +struct IgnoreCase_EqualTo { + bool operator()(const String& x, const String& y) const { return x.equalsIgnoreCase(y); } +}; + +struct IgnoreCase_Hash { + uint operator()(const String& x) const { return hashit_lower(x.c_str()); } +}; + + + +// Specalization of the Hash functor for String objects. +// We do case sensitve hashing here, because that is what +// the default EqualTo is compatible with. If one wants to use +// case insensitve hashing, then only because one wants to use +// IgnoreCase_EqualTo, and then one has to specify a custom +// hash anyway. +template<> +struct Hash<String> { + uint operator()(const String& s) const { + return hashit(s.c_str()); + } +}; + +template<> +struct Hash<const char *> { + uint operator()(const char *s) const { + return hashit(s); + } +}; + +// String map -- by default case insensitive +typedef HashMap<String, String, IgnoreCase_Hash, IgnoreCase_EqualTo> StringMap; + + + +} // End of namespace Common + + +#endif diff --git a/devtools/create_xeen/hashmap.cpp b/devtools/create_xeen/hashmap.cpp new file mode 100644 index 0000000000..99840993ce --- /dev/null +++ b/devtools/create_xeen/hashmap.cpp @@ -0,0 +1,109 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +// The hash map (associative array) implementation in this file is +// based on the PyDict implementation of CPython. The erase() method +// is based on example code in the Wikipedia article on Hash tables. + +#include "common/hashmap.h" + +namespace Common { + +// Hash function for strings, taken from CPython. +uint hashit(const char *p) { + uint hash = *p << 7; + byte c; + int size = 0; + while ((c = *p++)) { + hash = (1000003 * hash) ^ c; + size++; + } + return hash ^ size; +} + +// Like hashit, but converts every char to lowercase before hashing. +uint hashit_lower(const char *p) { + uint hash = tolower(*p) << 7; + byte c; + int size = 0; + while ((c = *p++)) { + hash = (1000003 * hash) ^ tolower(c); + size++; + } + return hash ^ size; +} + +#ifdef DEBUG_HASH_COLLISIONS +static double + g_collisions = 0, + g_dummyHits = 0, + g_lookups = 0, + g_collPerLook = 0, + g_capacity = 0, + g_size = 0; +static int g_max_capacity = 0, g_max_size = 0; +static int g_totalHashmaps = 0; +static int g_stats[4] = {0,0,0,0}; + +void updateHashCollisionStats(int collisions, int dummyHits, int lookups, int arrsize, int nele) { + g_collisions += collisions; + g_lookups += lookups; + g_dummyHits += dummyHits; + if (lookups) + g_collPerLook += (double)collisions / (double)lookups; + g_capacity += arrsize; + g_size += nele; + g_totalHashmaps++; + + if (3*nele <= 2*8) + g_stats[0]++; + if (3*nele <= 2*16) + g_stats[1]++; + if (3*nele <= 2*32) + g_stats[2]++; + if (3*nele <= 2*64) + g_stats[3]++; + + g_max_capacity = MAX(g_max_capacity, arrsize); + g_max_size = MAX(g_max_size, nele); + + debug("%d hashmaps: colls %.1f; dummies hit %.1f, lookups %.1f; ratio %.3f%%; size %f (max: %d); capacity %f (max: %d)", + g_totalHashmaps, + g_collisions / g_totalHashmaps, + g_dummyHits / g_totalHashmaps, + g_lookups / g_totalHashmaps, + 100 * g_collPerLook / g_totalHashmaps, + g_size / g_totalHashmaps, g_max_size, + g_capacity / g_totalHashmaps, g_max_capacity); + debug(" %d less than %d; %d less than %d; %d less than %d; %d less than %d", + g_stats[0], 2*8/3, + g_stats[1],2*16/3, + g_stats[2],2*32/3, + g_stats[3],2*64/3); + + // TODO: + // * Should record the maximal size of the map during its lifetime, not that at its death + // * Should do some statistics: how many maps are less than 2/3*8, 2/3*16, 2/3*32, ... +} +#endif + +} // End of namespace Common diff --git a/devtools/create_xeen/hashmap.h b/devtools/create_xeen/hashmap.h new file mode 100644 index 0000000000..c8691aeb42 --- /dev/null +++ b/devtools/create_xeen/hashmap.h @@ -0,0 +1,637 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +// The hash map (associative array) implementation in this file is +// based on the PyDict implementation of CPython. + +#ifndef COMMON_HASHMAP_H +#define COMMON_HASHMAP_H + +/** + * @def DEBUG_HASH_COLLISIONS + * Enable the following #define if you want to check how many collisions the + * code produces (many collisions indicate either a bad hash function, or a + * hash table that is too small). + */ +//#define DEBUG_HASH_COLLISIONS + +/** + * @def USE_HASHMAP_MEMORY_POOL + * Enable the following define to let HashMaps use a memory pool for the + nodes they contain. * This increases memory usage, but also can improve + speed quite a bit. + */ +#define USE_HASHMAP_MEMORY_POOL + + +#include "common/func.h" + +#ifdef DEBUG_HASH_COLLISIONS +#include "common/debug.h" +#endif + +#ifdef USE_HASHMAP_MEMORY_POOL +#include "memorypool.h" +#endif + + + +namespace Common { + +// The sgi IRIX MIPSpro Compiler has difficulties with nested templates. +// This and the other __sgi conditionals below work around these problems. +// The Intel C++ Compiler suffers from the same problems. +#if (defined(__sgi) && !defined(__GNUC__)) || defined(__INTEL_COMPILER) +template<class T> class IteratorImpl; +#endif + + +/** + * HashMap<Key,Val> maps objects of type Key to objects of type Val. + * For each used Key type, we need an "size_type hashit(Key,size_type)" function + * that computes a hash for the given Key object and returns it as an + * an integer from 0 to hashsize-1, and also an "equality functor". + * that returns true if if its two arguments are to be considered + * equal. Also, we assume that "=" works on Val objects for assignment. + * + * If aa is an HashMap<Key,Val>, then space is allocated each time aa[key] is + * referenced, for a new key. If the object is const, then an assertion is + * triggered instead. Hence if you are not sure whether a key is contained in + * the map, use contains() first to check for its presence. + */ +template<class Key, class Val, class HashFunc = Hash<Key>, class EqualFunc = EqualTo<Key> > +class HashMap { +public: + typedef uint size_type; + +private: + + typedef HashMap<Key, Val, HashFunc, EqualFunc> HM_t; + + struct Node { + const Key _key; + Val _value; + explicit Node(const Key &key) : _key(key), _value() {} + Node() : _key(), _value() {} + }; + + enum { + HASHMAP_PERTURB_SHIFT = 5, + HASHMAP_MIN_CAPACITY = 16, + + // The quotient of the next two constants controls how much the + // internal storage of the hashmap may fill up before being + // increased automatically. + // Note: the quotient of these two must be between and different + // from 0 and 1. + HASHMAP_LOADFACTOR_NUMERATOR = 2, + HASHMAP_LOADFACTOR_DENOMINATOR = 3, + + HASHMAP_MEMORYPOOL_SIZE = HASHMAP_MIN_CAPACITY * HASHMAP_LOADFACTOR_NUMERATOR / HASHMAP_LOADFACTOR_DENOMINATOR + }; + +#ifdef USE_HASHMAP_MEMORY_POOL + ObjectPool<Node, HASHMAP_MEMORYPOOL_SIZE> _nodePool; +#endif + + Node **_storage; ///< hashtable of size arrsize. + size_type _mask; ///< Capacity of the HashMap minus one; must be a power of two of minus one + size_type _size; + size_type _deleted; ///< Number of deleted elements (_dummyNodes) + + HashFunc _hash; + EqualFunc _equal; + + /** Default value, returned by the const getVal. */ + const Val _defaultVal; + + /** Dummy node, used as marker for erased objects. */ + #define HASHMAP_DUMMY_NODE ((Node *)1) + +#ifdef DEBUG_HASH_COLLISIONS + mutable int _collisions, _lookups, _dummyHits; +#endif + + Node *allocNode(const Key &key) { +#ifdef USE_HASHMAP_MEMORY_POOL + return new (_nodePool) Node(key); +#else + return new Node(key); +#endif + } + + void freeNode(Node *node) { + if (node && node != HASHMAP_DUMMY_NODE) +#ifdef USE_HASHMAP_MEMORY_POOL + _nodePool.deleteChunk(node); +#else + delete node; +#endif + } + + void assign(const HM_t &map); + size_type lookup(const Key &key) const; + size_type lookupAndCreateIfMissing(const Key &key); + void expandStorage(size_type newCapacity); + +#if !defined(__sgi) || defined(__GNUC__) + template<class T> friend class IteratorImpl; +#endif + + /** + * Simple HashMap iterator implementation. + */ + template<class NodeType> + class IteratorImpl { + friend class HashMap; +#if (defined(__sgi) && !defined(__GNUC__)) || defined(__INTEL_COMPILER) + template<class T> friend class Common::IteratorImpl; +#else + template<class T> friend class IteratorImpl; +#endif + protected: + typedef const HashMap hashmap_t; + + size_type _idx; + hashmap_t *_hashmap; + + protected: + IteratorImpl(size_type idx, hashmap_t *hashmap) : _idx(idx), _hashmap(hashmap) {} + + NodeType *deref() const { + assert(_hashmap != 0); + assert(_idx <= _hashmap->_mask); + Node *node = _hashmap->_storage[_idx]; + assert(node != 0); + assert(node != HASHMAP_DUMMY_NODE); + return node; + } + + public: + IteratorImpl() : _idx(0), _hashmap(0) {} + template<class T> + IteratorImpl(const IteratorImpl<T> &c) : _idx(c._idx), _hashmap(c._hashmap) {} + + NodeType &operator*() const { return *deref(); } + NodeType *operator->() const { return deref(); } + + bool operator==(const IteratorImpl &iter) const { return _idx == iter._idx && _hashmap == iter._hashmap; } + bool operator!=(const IteratorImpl &iter) const { return !(*this == iter); } + + IteratorImpl &operator++() { + assert(_hashmap); + do { + _idx++; + } while (_idx <= _hashmap->_mask && (_hashmap->_storage[_idx] == 0 || _hashmap->_storage[_idx] == HASHMAP_DUMMY_NODE)); + if (_idx > _hashmap->_mask) + _idx = (size_type)-1; + + return *this; + } + + IteratorImpl operator++(int) { + IteratorImpl old = *this; + operator ++(); + return old; + } + }; + +public: + typedef IteratorImpl<Node> iterator; + typedef IteratorImpl<const Node> const_iterator; + + HashMap(); + HashMap(const HM_t &map); + ~HashMap(); + + HM_t &operator=(const HM_t &map) { + if (this == &map) + return *this; + + // Remove the previous content and ... + clear(); + delete[] _storage; + // ... copy the new stuff. + assign(map); + return *this; + } + + bool contains(const Key &key) const; + + Val &operator[](const Key &key); + const Val &operator[](const Key &key) const; + + Val &getVal(const Key &key); + const Val &getVal(const Key &key) const; + const Val &getVal(const Key &key, const Val &defaultVal) const; + void setVal(const Key &key, const Val &val); + + void clear(bool shrinkArray = 0); + + void erase(iterator entry); + void erase(const Key &key); + + size_type size() const { return _size; } + + iterator begin() { + // Find and return the first non-empty entry + for (size_type ctr = 0; ctr <= _mask; ++ctr) { + if (_storage[ctr] && _storage[ctr] != HASHMAP_DUMMY_NODE) + return iterator(ctr, this); + } + return end(); + } + iterator end() { + return iterator((size_type)-1, this); + } + + const_iterator begin() const { + // Find and return the first non-empty entry + for (size_type ctr = 0; ctr <= _mask; ++ctr) { + if (_storage[ctr] && _storage[ctr] != HASHMAP_DUMMY_NODE) + return const_iterator(ctr, this); + } + return end(); + } + const_iterator end() const { + return const_iterator((size_type)-1, this); + } + + iterator find(const Key &key) { + size_type ctr = lookup(key); + if (_storage[ctr]) + return iterator(ctr, this); + return end(); + } + + const_iterator find(const Key &key) const { + size_type ctr = lookup(key); + if (_storage[ctr]) + return const_iterator(ctr, this); + return end(); + } + + // TODO: insert() method? + + bool empty() const { + return (_size == 0); + } +}; + +//------------------------------------------------------- +// HashMap functions + +/** + * Base constructor, creates an empty hashmap. + */ +template<class Key, class Val, class HashFunc, class EqualFunc> +HashMap<Key, Val, HashFunc, EqualFunc>::HashMap() +// +// We have to skip _defaultVal() on PS2 to avoid gcc 3.2.2 ICE +// +#ifdef __PLAYSTATION2__ + { +#else + : _defaultVal() { +#endif + _mask = HASHMAP_MIN_CAPACITY - 1; + _storage = new Node *[HASHMAP_MIN_CAPACITY]; + assert(_storage != NULL); + memset(_storage, 0, HASHMAP_MIN_CAPACITY * sizeof(Node *)); + + _size = 0; + _deleted = 0; + +#ifdef DEBUG_HASH_COLLISIONS + _collisions = 0; + _lookups = 0; + _dummyHits = 0; +#endif +} + +/** + * Copy constructor, creates a full copy of the given hashmap. + * We must provide a custom copy constructor as we use pointers + * to heap buffers for the internal storage. + */ +template<class Key, class Val, class HashFunc, class EqualFunc> +HashMap<Key, Val, HashFunc, EqualFunc>::HashMap(const HM_t &map) : + _defaultVal() { +#ifdef DEBUG_HASH_COLLISIONS + _collisions = 0; + _lookups = 0; + _dummyHits = 0; +#endif + assign(map); +} + +/** + * Destructor, frees all used memory. + */ +template<class Key, class Val, class HashFunc, class EqualFunc> +HashMap<Key, Val, HashFunc, EqualFunc>::~HashMap() { + for (size_type ctr = 0; ctr <= _mask; ++ctr) + freeNode(_storage[ctr]); + + delete[] _storage; +#ifdef DEBUG_HASH_COLLISIONS + extern void updateHashCollisionStats(int, int, int, int, int); + updateHashCollisionStats(_collisions, _dummyHits, _lookups, _mask+1, _size); +#endif +} + +/** + * Internal method for assigning the content of another HashMap + * to this one. + * + * @note We do *not* deallocate the previous storage here -- the caller is + * responsible for doing that! + */ +template<class Key, class Val, class HashFunc, class EqualFunc> +void HashMap<Key, Val, HashFunc, EqualFunc>::assign(const HM_t &map) { + _mask = map._mask; + _storage = new Node *[_mask+1]; + assert(_storage != NULL); + memset(_storage, 0, (_mask+1) * sizeof(Node *)); + + // Simply clone the map given to us, one by one. + _size = 0; + _deleted = 0; + for (size_type ctr = 0; ctr <= _mask; ++ctr) { + if (map._storage[ctr] == HASHMAP_DUMMY_NODE) { + _storage[ctr] = HASHMAP_DUMMY_NODE; + _deleted++; + } else if (map._storage[ctr] != NULL) { + _storage[ctr] = allocNode(map._storage[ctr]->_key); + _storage[ctr]->_value = map._storage[ctr]->_value; + _size++; + } + } + // Perform a sanity check (to help track down hashmap corruption) + assert(_size == map._size); + assert(_deleted == map._deleted); +} + + +template<class Key, class Val, class HashFunc, class EqualFunc> +void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) { + for (size_type ctr = 0; ctr <= _mask; ++ctr) { + freeNode(_storage[ctr]); + _storage[ctr] = NULL; + } + +#ifdef USE_HASHMAP_MEMORY_POOL + _nodePool.freeUnusedPages(); +#endif + + if (shrinkArray && _mask >= HASHMAP_MIN_CAPACITY) { + delete[] _storage; + + _mask = HASHMAP_MIN_CAPACITY; + _storage = new Node *[HASHMAP_MIN_CAPACITY]; + assert(_storage != NULL); + memset(_storage, 0, HASHMAP_MIN_CAPACITY * sizeof(Node *)); + } + + _size = 0; + _deleted = 0; +} + +template<class Key, class Val, class HashFunc, class EqualFunc> +void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(size_type newCapacity) { + assert(newCapacity > _mask+1); + +#ifndef NDEBUG + const size_type old_size = _size; +#endif + const size_type old_mask = _mask; + Node **old_storage = _storage; + + // allocate a new array + _size = 0; + _deleted = 0; + _mask = newCapacity - 1; + _storage = new Node *[newCapacity]; + assert(_storage != NULL); + memset(_storage, 0, newCapacity * sizeof(Node *)); + + // rehash all the old elements + for (size_type ctr = 0; ctr <= old_mask; ++ctr) { + if (old_storage[ctr] == NULL || old_storage[ctr] == HASHMAP_DUMMY_NODE) + continue; + + // Insert the element from the old table into the new table. + // Since we know that no key exists twice in the old table, we + // can do this slightly better than by calling lookup, since we + // don't have to call _equal(). + const size_type hash = _hash(old_storage[ctr]->_key); + size_type idx = hash & _mask; + for (size_type perturb = hash; _storage[idx] != NULL && _storage[idx] != HASHMAP_DUMMY_NODE; perturb >>= HASHMAP_PERTURB_SHIFT) { + idx = (5 * idx + perturb + 1) & _mask; + } + + _storage[idx] = old_storage[ctr]; + _size++; + } + + // Perform a sanity check: Old number of elements should match the new one! + // This check will fail if some previous operation corrupted this hashmap. + assert(_size == old_size); + + delete[] old_storage; + + return; +} + +template<class Key, class Val, class HashFunc, class EqualFunc> +typename HashMap<Key, Val, HashFunc, EqualFunc>::size_type HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const { + const size_type hash = _hash(key); + size_type ctr = hash & _mask; + for (size_type perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) { + if (_storage[ctr] == NULL) + break; + if (_storage[ctr] == HASHMAP_DUMMY_NODE) { +#ifdef DEBUG_HASH_COLLISIONS + _dummyHits++; +#endif + } else if (_equal(_storage[ctr]->_key, key)) + break; + + ctr = (5 * ctr + perturb + 1) & _mask; + +#ifdef DEBUG_HASH_COLLISIONS + _collisions++; +#endif + } + +#ifdef DEBUG_HASH_COLLISIONS + _lookups++; + debug("collisions %d, dummies hit %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d", + _collisions, _dummyHits, _lookups, ((double) _collisions / (double)_lookups), + (const void *)this, _mask+1, _size); +#endif + + return ctr; +} + +template<class Key, class Val, class HashFunc, class EqualFunc> +typename HashMap<Key, Val, HashFunc, EqualFunc>::size_type HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &key) { + const size_type hash = _hash(key); + size_type ctr = hash & _mask; + const size_type NONE_FOUND = _mask + 1; + size_type first_free = NONE_FOUND; + bool found = false; + for (size_type perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) { + if (_storage[ctr] == NULL) + break; + if (_storage[ctr] == HASHMAP_DUMMY_NODE) { +#ifdef DEBUG_HASH_COLLISIONS + _dummyHits++; +#endif + if (first_free != _mask + 1) + first_free = ctr; + } else if (_equal(_storage[ctr]->_key, key)) { + found = true; + break; + } + + ctr = (5 * ctr + perturb + 1) & _mask; + +#ifdef DEBUG_HASH_COLLISIONS + _collisions++; +#endif + } + +#ifdef DEBUG_HASH_COLLISIONS + _lookups++; + debug("collisions %d, dummies hit %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d", + _collisions, _dummyHits, _lookups, ((double) _collisions / (double)_lookups), + (const void *)this, _mask+1, _size); +#endif + + if (!found && first_free != _mask + 1) + ctr = first_free; + + if (!found) { + if (_storage[ctr]) + _deleted--; + _storage[ctr] = allocNode(key); + assert(_storage[ctr] != NULL); + _size++; + + // Keep the load factor below a certain threshold. + // Deleted nodes are also counted + size_type capacity = _mask + 1; + if ((_size + _deleted) * HASHMAP_LOADFACTOR_DENOMINATOR > + capacity * HASHMAP_LOADFACTOR_NUMERATOR) { + capacity = capacity < 500 ? (capacity * 4) : (capacity * 2); + expandStorage(capacity); + ctr = lookup(key); + assert(_storage[ctr] != NULL); + } + } + + return ctr; +} + + +template<class Key, class Val, class HashFunc, class EqualFunc> +bool HashMap<Key, Val, HashFunc, EqualFunc>::contains(const Key &key) const { + size_type ctr = lookup(key); + return (_storage[ctr] != NULL); +} + +template<class Key, class Val, class HashFunc, class EqualFunc> +Val &HashMap<Key, Val, HashFunc, EqualFunc>::operator[](const Key &key) { + return getVal(key); +} + +template<class Key, class Val, class HashFunc, class EqualFunc> +const Val &HashMap<Key, Val, HashFunc, EqualFunc>::operator[](const Key &key) const { + return getVal(key); +} + +template<class Key, class Val, class HashFunc, class EqualFunc> +Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) { + size_type ctr = lookupAndCreateIfMissing(key); + assert(_storage[ctr] != NULL); + return _storage[ctr]->_value; +} + +template<class Key, class Val, class HashFunc, class EqualFunc> +const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) const { + return getVal(key, _defaultVal); +} + +template<class Key, class Val, class HashFunc, class EqualFunc> +const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key, const Val &defaultVal) const { + size_type ctr = lookup(key); + if (_storage[ctr] != NULL) + return _storage[ctr]->_value; + else + return defaultVal; +} + +template<class Key, class Val, class HashFunc, class EqualFunc> +void HashMap<Key, Val, HashFunc, EqualFunc>::setVal(const Key &key, const Val &val) { + size_type ctr = lookupAndCreateIfMissing(key); + assert(_storage[ctr] != NULL); + _storage[ctr]->_value = val; +} + +template<class Key, class Val, class HashFunc, class EqualFunc> +void HashMap<Key, Val, HashFunc, EqualFunc>::erase(iterator entry) { + // Check whether we have a valid iterator + assert(entry._hashmap == this); + const size_type ctr = entry._idx; + assert(ctr <= _mask); + Node * const node = _storage[ctr]; + assert(node != NULL); + assert(node != HASHMAP_DUMMY_NODE); + + // If we remove a key, we replace it with a dummy node. + freeNode(node); + _storage[ctr] = HASHMAP_DUMMY_NODE; + _size--; + _deleted++; +} + +template<class Key, class Val, class HashFunc, class EqualFunc> +void HashMap<Key, Val, HashFunc, EqualFunc>::erase(const Key &key) { + + size_type ctr = lookup(key); + if (_storage[ctr] == NULL) + return; + + // If we remove a key, we replace it with a dummy node. + freeNode(_storage[ctr]); + _storage[ctr] = HASHMAP_DUMMY_NODE; + _size--; + _deleted++; + return; +} + +#undef HASHMAP_DUMMY_NODE + +} // End of namespace Common + +#endif diff --git a/devtools/create_xeen/memorypool.cpp b/devtools/create_xeen/memorypool.cpp new file mode 100644 index 0000000000..13c640b6ad --- /dev/null +++ b/devtools/create_xeen/memorypool.cpp @@ -0,0 +1,182 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 "memorypool.h" +#include "common/util.h" + +namespace Common { + +enum { + INITIAL_CHUNKS_PER_PAGE = 8 +}; + +static size_t adjustChunkSize(size_t chunkSize) { + // You must at least fit the pointer in the node (technically unneeded considering the next rounding statement) + chunkSize = MAX(chunkSize, sizeof(void *)); + // There might be an alignment problem on some platforms when trying to load a void* on a non natural boundary + // so we round to the next sizeof(void *) + chunkSize = (chunkSize + sizeof(void *) - 1) & (~(sizeof(void *) - 1)); + + return chunkSize; +} + + +MemoryPool::MemoryPool(size_t chunkSize) + : _chunkSize(adjustChunkSize(chunkSize)) { + + _next = NULL; + + _chunksPerPage = INITIAL_CHUNKS_PER_PAGE; +} + +MemoryPool::~MemoryPool() { +#if 0 + freeUnusedPages(); + if (!_pages.empty()) + warning("Memory leak found in pool"); +#endif + + for (size_t i = 0; i < _pages.size(); ++i) + ::free(_pages[i].start); +} + +void MemoryPool::allocPage() { + Page page; + + // Allocate a new page + page.numChunks = _chunksPerPage; + assert(page.numChunks * _chunkSize < 16*1024*1024); // Refuse to allocate pages bigger than 16 MB + + page.start = ::malloc(page.numChunks * _chunkSize); + assert(page.start); + _pages.push_back(page); + + + // Next time, we'll allocate a page twice as big as this one. + _chunksPerPage *= 2; + + // Add the page to the pool of free chunk + addPageToPool(page); +} + +void MemoryPool::addPageToPool(const Page &page) { + // Add all chunks of the new page to the linked list (pool) of free chunks + void *current = page.start; + for (size_t i = 1; i < page.numChunks; ++i) { + void *next = (byte *)current + _chunkSize; + *(void **)current = next; + + current = next; + } + + // Last chunk points to the old _next + *(void **)current = _next; + + // From now on, the first free chunk is the first chunk of the new page + _next = page.start; +} + +void *MemoryPool::allocChunk() { + // No free chunks left? Allocate a new page + if (!_next) + allocPage(); + + assert(_next); + void *result = _next; + _next = *(void **)result; + return result; +} + +void MemoryPool::freeChunk(void *ptr) { + // Add the chunk back to (the start of) the list of free chunks + *(void **)ptr = _next; + _next = ptr; +} + +// Technically not compliant C++ to compare unrelated pointers. In practice... +bool MemoryPool::isPointerInPage(void *ptr, const Page &page) { + return (ptr >= page.start) && (ptr < (char *)page.start + page.numChunks * _chunkSize); +} + +void MemoryPool::freeUnusedPages() { + //std::sort(_pages.begin(), _pages.end()); + Array<size_t> numberOfFreeChunksPerPage; + numberOfFreeChunksPerPage.resize(_pages.size()); + for (size_t i = 0; i < numberOfFreeChunksPerPage.size(); ++i) { + numberOfFreeChunksPerPage[i] = 0; + } + + // Compute for each page how many chunks in it are still in use. + void *iterator = _next; + while (iterator) { + // TODO: This should be a binary search (requiring us to keep _pages sorted) + for (size_t i = 0; i < _pages.size(); ++i) { + if (isPointerInPage(iterator, _pages[i])) { + ++numberOfFreeChunksPerPage[i]; + break; + } + } + + iterator = *(void **)iterator; + } + + // Free all pages which are not in use. + size_t freedPagesCount = 0; + for (size_t i = 0; i < _pages.size(); ++i) { + if (numberOfFreeChunksPerPage[i] == _pages[i].numChunks) { + // Remove all chunks of this page from the list of free chunks + void **iter2 = &_next; + while (*iter2) { + if (isPointerInPage(*iter2, _pages[i])) + *iter2 = **(void ***)iter2; + else + iter2 = *(void ***)iter2; + } + + ::free(_pages[i].start); + ++freedPagesCount; + _pages[i].start = NULL; + } + } + +// debug("freed %d pages out of %d", (int)freedPagesCount, (int)_pages.size()); + + // Remove all now unused pages + size_t newSize = 0; + for (size_t i = 0; i < _pages.size(); ++i) { + if (_pages[i].start != NULL) { + if (newSize != i) + _pages[newSize] = _pages[i]; + ++newSize; + } + } + _pages.resize(newSize); + + // Reset _chunksPerPage + _chunksPerPage = INITIAL_CHUNKS_PER_PAGE; + for (size_t i = 0; i < _pages.size(); ++i) { + if (_chunksPerPage < _pages[i].numChunks) + _chunksPerPage = _pages[i].numChunks; + } +} + +} // End of namespace Common diff --git a/devtools/create_xeen/memorypool.h b/devtools/create_xeen/memorypool.h new file mode 100644 index 0000000000..c8a8fc7a53 --- /dev/null +++ b/devtools/create_xeen/memorypool.h @@ -0,0 +1,162 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 COMMON_MEMORYPOOL_H +#define COMMON_MEMORYPOOL_H + +#include "common/array.h" + + +namespace Common { + +/** + * This class provides a pool of memory 'chunks' of identical size. + * The size of a chunk is determined when creating the memory pool. + * + * Using a memory pool may yield better performance and memory usage + * when allocating and deallocating many memory blocks of equal size. + * E.g. the Common::String class uses a memory pool for the refCount + * variables (each the size of an int) it allocates for each string + * instance. + */ +class MemoryPool { +protected: + MemoryPool(const MemoryPool&); + MemoryPool& operator=(const MemoryPool&); + + struct Page { + void *start; + size_t numChunks; + }; + + const size_t _chunkSize; + Array<Page> _pages; + void *_next; + size_t _chunksPerPage; + + void allocPage(); + void addPageToPool(const Page &page); + bool isPointerInPage(void *ptr, const Page &page); + +public: + /** + * Constructor for a memory pool with the given chunk size. + * @param chunkSize the chunk size of this memory pool + */ + explicit MemoryPool(size_t chunkSize); + ~MemoryPool(); + + /** + * Allocate a new chunk from the memory pool. + */ + void *allocChunk(); + /** + * Return a chunk to the memory pool. The given pointer must have + * been obtained from calling the allocChunk() method of the very + * same MemoryPool instance. Passing any other pointer (e.g. to + * a chunk from another MemoryPool, or a malloc'ed memory block) + * will lead to undefined behavior and may result in a crash (if + * you are lucky) or in silent data corruption. + */ + void freeChunk(void *ptr); + + /** + * Perform garbage collection. The memory pool stores all the + * chunks it manages in memory 'pages' obtained via the classic + * memory allocation APIs (i.e. malloc/free). Ordinarily, once + * a page has been allocated, it won't be released again during + * the life time of the memory pool. The exception is when this + * method is called. + */ + void freeUnusedPages(); + + /** + * Return the chunk size used by this memory pool. + */ + size_t getChunkSize() const { return _chunkSize; } +}; + +/** + * This is a memory pool which already contains in itself some storage + * space for a fixed number of chunks. Thus if the memory pool is only + * lightly used, no malloc() calls have to be made at all. + */ +template<size_t CHUNK_SIZE, size_t NUM_INTERNAL_CHUNKS = 32> +class FixedSizeMemoryPool : public MemoryPool { +private: + enum { + REAL_CHUNK_SIZE = (CHUNK_SIZE + sizeof(void *) - 1) & (~(sizeof(void *) - 1)) + }; + + byte _storage[NUM_INTERNAL_CHUNKS * REAL_CHUNK_SIZE]; +public: + FixedSizeMemoryPool() : MemoryPool(CHUNK_SIZE) { + assert(REAL_CHUNK_SIZE == _chunkSize); + // Insert some static storage + Page internalPage = { _storage, NUM_INTERNAL_CHUNKS }; + addPageToPool(internalPage); + } +}; + +// Ensure NUM_INTERNAL_CHUNKS == 0 results in a compile error +template<size_t CHUNK_SIZE> +class FixedSizeMemoryPool<CHUNK_SIZE,0> : public MemoryPool { +public: + FixedSizeMemoryPool() : MemoryPool(CHUNK_SIZE) {} +}; + +/** + * A memory pool for C++ objects. + */ +template<class T, size_t NUM_INTERNAL_CHUNKS = 32> +class ObjectPool : public FixedSizeMemoryPool<sizeof(T), NUM_INTERNAL_CHUNKS> { +public: + /** + * Return the memory chunk used as storage for the given object back + * to the pool, after calling its destructor. + */ + void deleteChunk(T *ptr) { + ptr->~T(); + this->freeChunk(ptr); + } +}; + +} // End of namespace Common + +/** + * A custom placement new operator, using an arbitrary MemoryPool. + * + * This *should* work with all C++ implementations, but may not. + * + * For details on using placement new for custom allocators, see e.g. + * <http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.14> + */ +inline void *operator new(size_t nbytes, Common::MemoryPool &pool) { + assert(nbytes <= pool.getChunkSize()); + return pool.allocChunk(); +} + +inline void operator delete(void *p, Common::MemoryPool &pool) { + pool.freeChunk(p); +} + +#endif diff --git a/devtools/create_xeen/module.mk b/devtools/create_xeen/module.mk new file mode 100644 index 0000000000..d382fc6bd6 --- /dev/null +++ b/devtools/create_xeen/module.mk @@ -0,0 +1,15 @@ +MODULE := devtools/create_xeen + +MODULE_OBJS := \ + create_xeen.o \ + cc.o \ + constants.o \ + hashmap.o \ + memorypool.o \ + str.o + +# Set the name of the executable +TOOL_EXECUTABLE := create_xeen + +# Include common rules +include $(srcdir)/rules.mk diff --git a/devtools/create_xeen/str.cpp b/devtools/create_xeen/str.cpp new file mode 100644 index 0000000000..6aa66d0d20 --- /dev/null +++ b/devtools/create_xeen/str.cpp @@ -0,0 +1,786 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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/hash-str.h" +#include "common/list.h" +#include "memorypool.h" +#include "common/str.h" +#include "common/util.h" + +namespace Common { + +MemoryPool *g_refCountPool = 0; // FIXME: This is never freed right now + +static uint32 computeCapacity(uint32 len) { + // By default, for the capacity we use the next multiple of 32 + return ((len + 32 - 1) & ~0x1F); +} + +String::String(const char *str) : _size(0), _str(_storage) { + if (str == 0) { + _storage[0] = 0; + _size = 0; + } else + initWithCStr(str, strlen(str)); +} + +String::String(const char *str, uint32 len) : _size(0), _str(_storage) { + initWithCStr(str, len); +} + +String::String(const char *beginP, const char *endP) : _size(0), _str(_storage) { + assert(endP >= beginP); + initWithCStr(beginP, endP - beginP); +} + +void String::initWithCStr(const char *str, uint32 len) { + assert(str); + + // Init _storage member explicitly (ie. without calling its constructor) + // for GCC 2.95.x compatibility (see also tracker item #1602879). + _storage[0] = 0; + + _size = len; + + if (len >= _builtinCapacity) { + // Not enough internal storage, so allocate more + _extern._capacity = computeCapacity(len+1); + _extern._refCount = 0; + _str = new char[_extern._capacity]; + assert(_str != 0); + } + + // Copy the string into the storage area + memmove(_str, str, len); + _str[len] = 0; +} + +String::String(const String &str) + : _size(str._size) { + if (str.isStorageIntern()) { + // String in internal storage: just copy it + memcpy(_storage, str._storage, _builtinCapacity); + _str = _storage; + } else { + // String in external storage: use refcount mechanism + str.incRefCount(); + _extern._refCount = str._extern._refCount; + _extern._capacity = str._extern._capacity; + _str = str._str; + } + assert(_str != 0); +} + +String::String(char c) + : _size(0), _str(_storage) { + + _storage[0] = c; + _storage[1] = 0; + + _size = (c == 0) ? 0 : 1; +} + +String::~String() { + decRefCount(_extern._refCount); +} + +void String::makeUnique() { + ensureCapacity(_size, true); +} + +/** + * Ensure that enough storage is available to store at least new_size + * characters plus a null byte. In addition, if we currently share + * the storage with another string, unshare it, so that we can safely + * write to the storage. + */ +void String::ensureCapacity(uint32 new_size, bool keep_old) { + bool isShared; + uint32 curCapacity, newCapacity; + char *newStorage; + int *oldRefCount = _extern._refCount; + + if (isStorageIntern()) { + isShared = false; + curCapacity = _builtinCapacity; + } else { + isShared = (oldRefCount && *oldRefCount > 1); + curCapacity = _extern._capacity; + } + + // Special case: If there is enough space, and we do not share + // the storage, then there is nothing to do. + if (!isShared && new_size < curCapacity) + return; + + if (isShared && new_size < _builtinCapacity) { + // We share the storage, but there is enough internal storage: Use that. + newStorage = _storage; + newCapacity = _builtinCapacity; + } else { + // We need to allocate storage on the heap! + + // Compute a suitable new capacity limit + // If the current capacity is sufficient we use the same capacity + if (new_size < curCapacity) + newCapacity = curCapacity; + else + newCapacity = MAX(curCapacity * 2, computeCapacity(new_size+1)); + + // Allocate new storage + newStorage = new char[newCapacity]; + assert(newStorage); + } + + // Copy old data if needed, elsewise reset the new storage. + if (keep_old) { + assert(_size < newCapacity); + memcpy(newStorage, _str, _size + 1); + } else { + _size = 0; + newStorage[0] = 0; + } + + // Release hold on the old storage ... + decRefCount(oldRefCount); + + // ... in favor of the new storage + _str = newStorage; + + if (!isStorageIntern()) { + // Set the ref count & capacity if we use an external storage. + // It is important to do this *after* copying any old content, + // else we would override data that has not yet been copied! + _extern._refCount = 0; + _extern._capacity = newCapacity; + } +} + +void String::incRefCount() const { + assert(!isStorageIntern()); + if (_extern._refCount == 0) { + if (g_refCountPool == 0) { + g_refCountPool = new MemoryPool(sizeof(int)); + assert(g_refCountPool); + } + + _extern._refCount = (int *)g_refCountPool->allocChunk(); + *_extern._refCount = 2; + } else { + ++(*_extern._refCount); + } +} + +void String::decRefCount(int *oldRefCount) { + if (isStorageIntern()) + return; + + if (oldRefCount) { + --(*oldRefCount); + } + if (!oldRefCount || *oldRefCount <= 0) { + // The ref count reached zero, so we free the string storage + // and the ref count storage. + if (oldRefCount) { + assert(g_refCountPool); + g_refCountPool->freeChunk(oldRefCount); + } + delete[] _str; + + // Even though _str points to a freed memory block now, + // we do not change its value, because any code that calls + // decRefCount will have to do this afterwards anyway. + } +} + +String &String::operator=(const char *str) { + uint32 len = strlen(str); + ensureCapacity(len, false); + _size = len; + memmove(_str, str, len + 1); + return *this; +} + +String &String::operator=(const String &str) { + if (&str == this) + return *this; + + if (str.isStorageIntern()) { + decRefCount(_extern._refCount); + _size = str._size; + _str = _storage; + memcpy(_str, str._str, _size + 1); + } else { + str.incRefCount(); + decRefCount(_extern._refCount); + + _extern._refCount = str._extern._refCount; + _extern._capacity = str._extern._capacity; + _size = str._size; + _str = str._str; + } + + return *this; +} + +String &String::operator=(char c) { + decRefCount(_extern._refCount); + _str = _storage; + + _str[0] = c; + _str[1] = 0; + + _size = (c == 0) ? 0 : 1; + return *this; +} + +String &String::operator+=(const char *str) { + if (_str <= str && str <= _str + _size) + return operator+=(String(str)); + + int len = strlen(str); + if (len > 0) { + ensureCapacity(_size + len, true); + + memcpy(_str + _size, str, len + 1); + _size += len; + } + return *this; +} + +String &String::operator+=(const String &str) { + if (&str == this) + return operator+=(String(str)); + + int len = str._size; + if (len > 0) { + ensureCapacity(_size + len, true); + + memcpy(_str + _size, str._str, len + 1); + _size += len; + } + return *this; +} + +String &String::operator+=(char c) { + ensureCapacity(_size + 1, true); + + _str[_size++] = c; + _str[_size] = 0; + + return *this; +} + +bool String::hasPrefix(const String &x) const { + return hasPrefix(x.c_str()); +} + +bool String::hasPrefix(const char *x) const { + assert(x != 0); + // Compare x with the start of _str. + const char *y = c_str(); + while (*x && *x == *y) { + ++x; + ++y; + } + // It's a prefix, if and only if all letters in x are 'used up' before + // _str ends. + return *x == 0; +} + +bool String::hasSuffix(const String &x) const { + return hasSuffix(x.c_str()); +} + +bool String::hasSuffix(const char *x) const { + assert(x != 0); + // Compare x with the end of _str. + const uint32 x_size = strlen(x); + if (x_size > _size) + return false; + const char *y = c_str() + _size - x_size; + while (*x && *x == *y) { + ++x; + ++y; + } + // It's a suffix, if and only if all letters in x are 'used up' before + // _str ends. + return *x == 0; +} + +bool String::contains(const String &x) const { + return strstr(c_str(), x.c_str()) != NULL; +} + +bool String::contains(const char *x) const { + assert(x != 0); + return strstr(c_str(), x) != NULL; +} + +bool String::contains(char x) const { + return strchr(c_str(), x) != NULL; +} + +void String::deleteLastChar() { + if (_size > 0) + deleteChar(_size - 1); +} + +void String::deleteChar(uint32 p) { + assert(p < _size); + + makeUnique(); + while (p++ < _size) + _str[p - 1] = _str[p]; + _size--; +} + +void String::erase(uint32 p, uint32 len) { + assert(p < _size); + + makeUnique(); + // If len == npos or p + len is over the end, remove all the way to the end + if (len == npos || p + len >= _size) { + // Delete char at p as well. So _size = (p - 1) + 1 + _size = p; + // Null terminate + _str[_size] = 0; + return; + } + + for ( ; p + len <= _size; p++) { + _str[p] = _str[p + len]; + } + _size -= len; +} + +void String::clear() { + decRefCount(_extern._refCount); + + _size = 0; + _str = _storage; + _storage[0] = 0; +} + +void String::setChar(char c, uint32 p) { + assert(p < _size); + + makeUnique(); + _str[p] = c; +} + +void String::insertChar(char c, uint32 p) { + assert(p <= _size); + + ensureCapacity(_size + 1, true); + _size++; + for (uint32 i = _size; i > p; --i) + _str[i] = _str[i - 1]; + _str[p] = c; +} + +void String::toLowercase() { + makeUnique(); + for (uint32 i = 0; i < _size; ++i) + _str[i] = tolower(_str[i]); +} + +void String::toUppercase() { + makeUnique(); + for (uint32 i = 0; i < _size; ++i) + _str[i] = toupper(_str[i]); +} + +uint String::hash() const { + return hashit(c_str()); +} + +// static +String String::format(const char *fmt, ...) { + String output; + + va_list va; + va_start(va, fmt); + output = String::vformat(fmt, va); + va_end(va); + + return output; +} + +// static +String String::vformat(const char *fmt, va_list args) { + String output; + assert(output.isStorageIntern()); + + va_list va; + scumm_va_copy(va, args); + int len = vsnprintf(output._str, _builtinCapacity, fmt, va); + va_end(va); + + if (len == -1 || len == _builtinCapacity - 1) { + // MSVC and IRIX don't return the size the full string would take up. + // MSVC returns -1, IRIX returns the number of characters actually written, + // which is at the most the size of the buffer minus one, as the string is + // truncated to fit. + + // We assume MSVC failed to output the correct, null-terminated string + // if the return value is either -1 or size. + // For IRIX, because we lack a better mechanism, we assume failure + // if the return value equals size - 1. + // The downside to this is that whenever we try to format a string where the + // size is 1 below the built-in capacity, the size is needlessly increased. + + // Try increasing the size of the string until it fits. + int size = _builtinCapacity; + do { + size *= 2; + output.ensureCapacity(size - 1, false); + assert(!output.isStorageIntern()); + size = output._extern._capacity; + + scumm_va_copy(va, args); + len = vsnprintf(output._str, size, fmt, va); + va_end(va); + } while (len == -1 || len >= size - 1); + output._size = len; + } else if (len < (int)_builtinCapacity) { + // vsnprintf succeeded + output._size = len; + } else { + // vsnprintf didn't have enough space, so grow buffer + output.ensureCapacity(len, false); + scumm_va_copy(va, args); + int len2 = vsnprintf(output._str, len+1, fmt, va); + va_end(va); + assert(len == len2); + output._size = len2; + } + + return output; +} + + +#pragma mark - + +bool String::operator==(const String &x) const { + return equals(x); +} + +bool String::operator==(const char *x) const { + assert(x != 0); + return equals(x); +} + +bool String::operator!=(const String &x) const { + return !equals(x); +} + +bool String::operator !=(const char *x) const { + assert(x != 0); + return !equals(x); +} + +bool String::operator<(const String &x) const { + return compareTo(x) < 0; +} + +bool String::operator<=(const String &x) const { + return compareTo(x) <= 0; +} + +bool String::operator>(const String &x) const { + return compareTo(x) > 0; +} + +bool String::operator>=(const String &x) const { + return compareTo(x) >= 0; +} + +#pragma mark - + +bool operator==(const char* y, const String &x) { + return (x == y); +} + +bool operator!=(const char* y, const String &x) { + return x != y; +} + +#pragma mark - + +bool String::equals(const String &x) const { + return (0 == compareTo(x)); +} + +bool String::equals(const char *x) const { + assert(x != 0); + return (0 == compareTo(x)); +} + +bool String::equalsIgnoreCase(const String &x) const { + return (0 == compareToIgnoreCase(x)); +} + +bool String::equalsIgnoreCase(const char *x) const { + assert(x != 0); + return (0 == compareToIgnoreCase(x)); +} + +int String::compareTo(const String &x) const { + return compareTo(x.c_str()); +} + +int String::compareTo(const char *x) const { + assert(x != 0); + return strcmp(c_str(), x); +} + +int String::compareToIgnoreCase(const String &x) const { + return compareToIgnoreCase(x.c_str()); +} + +int String::compareToIgnoreCase(const char *x) const { + assert(x != 0); + return scumm_stricmp(c_str(), x); +} + +#pragma mark - + +String operator+(const String &x, const String &y) { + String temp(x); + temp += y; + return temp; +} + +String operator+(const char *x, const String &y) { + String temp(x); + temp += y; + return temp; +} + +String operator+(const String &x, const char *y) { + String temp(x); + temp += y; + return temp; +} + +String operator+(char x, const String &y) { + String temp(x); + temp += y; + return temp; +} + +String operator+(const String &x, char y) { + String temp(x); + temp += y; + return temp; +} + +String lastPathComponent(const String &path, const char sep) { + const char *str = path.c_str(); + const char *last = str + path.size(); + + // Skip over trailing slashes + while (last > str && *(last-1) == sep) + --last; + + // Path consisted of only slashes -> return empty string + if (last == str) + return String(); + + // Now scan the whole component + const char *first = last - 1; + while (first > str && *first != sep) + --first; + + if (*first == sep) + first++; + + return String(first, last); +} + +String normalizePath(const String &path, const char sep) { + if (path.empty()) + return path; + + const char *cur = path.c_str(); + String result; + + // If there is a leading slash, preserve that: + if (*cur == sep) { + result += sep; + // Skip over multiple leading slashes, so "//" equals "/" + while (*cur == sep) + ++cur; + } + + // Scan for path components till the end of the String + List<String> comps; + while (*cur != 0) { + const char *start = cur; + + // Scan till the next path separator resp. the end of the string + while (*cur != sep && *cur != 0) + cur++; + + const String component(start, cur); + + if (component.empty() || component == ".") { + // Skip empty components and dot components + } else if (!comps.empty() && component == ".." && comps.back() != "..") { + // If stack is non-empty and top is not "..", remove top + comps.pop_back(); + } else { + // Add the component to the stack + comps.push_back(component); + } + + // Skip over separator chars + while (*cur == sep) + cur++; + } + + // Finally, assemble all components back into a path + while (!comps.empty()) { + result += comps.front(); + comps.pop_front(); + if (!comps.empty()) + result += sep; + } + + return result; +} + +size_t strlcpy(char *dst, const char *src, size_t size) { + // Our backup of the source's start, we need this + // to calculate the source's length. + const char * const srcStart = src; + + // In case a non-empty size was specified we + // copy over (size - 1) bytes at max. + if (size != 0) { + // Copy over (size - 1) bytes at max. + while (--size != 0) { + if ((*dst++ = *src) == 0) + break; + ++src; + } + + // In case the source string was longer than the + // destination, we need to add a terminating + // zero. + if (size == 0) + *dst = 0; + } + + // Move to the terminating zero of the source + // string, we need this to determine the length + // of the source string. + while (*src) + ++src; + + // Return the source string's length. + return src - srcStart; +} + +size_t strlcat(char *dst, const char *src, size_t size) { + // In case the destination buffer does not contain + // space for at least 1 character, we will just + // return the source string's length. + if (size == 0) + return strlen(src); + + // Our backup of the source's start, we need this + // to calculate the source's length. + const char * const srcStart = src; + + // Our backup of the destination's start, we need + // this to calculate the destination's length. + const char * const dstStart = dst; + + // Search the end of the destination, but do not + // move past the terminating zero. + while (size-- != 0 && *dst != 0) + ++dst; + + // Calculate the destination's length; + const size_t dstLength = dst - dstStart; + + // In case we reached the end of the destination + // buffer before we had a chance to append any + // characters we will just return the destination + // length plus the source string's length. + if (size == 0) + return dstLength + strlen(srcStart); + + // Copy over all of the source that fits + // the destination buffer. We also need + // to take the terminating zero we will + // add into consideration. + while (size-- != 0 && *src != 0) + *dst++ = *src++; + *dst = 0; + + // Move to the terminating zero of the source + // string, we need this to determine the length + // of the source string. + while (*src) + ++src; + + // Return the total length of the result string + return dstLength + (src - srcStart); +} + +} // End of namespace Common + +// Portable implementation of stricmp / strcasecmp / strcmpi. +// TODO: Rename this to Common::strcasecmp +int scumm_stricmp(const char *s1, const char *s2) { + byte l1, l2; + do { + // Don't use ++ inside tolower, in case the macro uses its + // arguments more than once. + l1 = (byte)*s1++; + l1 = tolower(l1); + l2 = (byte)*s2++; + l2 = tolower(l2); + } while (l1 == l2 && l1 != 0); + return l1 - l2; +} + +// Portable implementation of strnicmp / strncasecmp / strncmpi. +// TODO: Rename this to Common::strncasecmp +int scumm_strnicmp(const char *s1, const char *s2, uint n) { + byte l1, l2; + do { + if (n-- == 0) + return 0; // no difference found so far -> signal equality + + // Don't use ++ inside tolower, in case the macro uses its + // arguments more than once. + l1 = (byte)*s1++; + l1 = tolower(l1); + l2 = (byte)*s2++; + l2 = tolower(l2); + } while (l1 == l2 && l1 != 0); + return l1 - l2; +} diff --git a/devtools/create_xeen/str.h b/devtools/create_xeen/str.h new file mode 100644 index 0000000000..2f954dcfca --- /dev/null +++ b/devtools/create_xeen/str.h @@ -0,0 +1,386 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 COMMON_STRING_H +#define COMMON_STRING_H + +#include "common/scummsys.h" + +#include <stdarg.h> + +namespace Common { + +/** + * Simple string class for ScummVM. Provides automatic storage managment, + * and overloads several operators in a 'natural' fashion, mimicking + * the std::string class. Even provides simple iterators. + * + * This class tries to avoid allocating lots of small blocks on the heap, + * since that is inefficient on several platforms supported by ScummVM. + * Instead, small strings are stored 'inside' the string object (i.e. on + * the stack, for stack allocated objects), and only for strings exceeding + * a certain length do we allocate a buffer on the heap. + * + * The presence of \0 characters in the string will cause undefined + * behavior in some operations. + */ +class String { +public: + static const uint32 npos = 0xFFFFFFFF; +protected: + /** + * The size of the internal storage. Increasing this means less heap + * allocations are needed, at the cost of more stack memory usage, + * and of course lots of wasted memory. Empirically, 90% or more of + * all String instances are less than 32 chars long. If a platform + * is very short on stack space, it would be possible to lower this. + * A value of 24 still seems acceptable, though considerably worse, + * while 16 seems to be the lowest you want to go... Anything lower + * than 8 makes no sense, since that's the size of member _extern + * (on 32 bit machines; 12 bytes on systems with 64bit pointers). + */ + static const uint32 _builtinCapacity = 32 - sizeof(uint32) - sizeof(char *); + + /** + * Length of the string. Stored to avoid having to call strlen + * a lot. Yes, we limit ourselves to strings shorter than 4GB -- + * on purpose :-). + */ + uint32 _size; + + /** + * Pointer to the actual string storage. Either points to _storage, + * or to a block allocated on the heap via malloc. + */ + char *_str; + + + union { + /** + * Internal string storage. + */ + char _storage[_builtinCapacity]; + /** + * External string storage data -- the refcounter, and the + * capacity of the string _str points to. + */ + struct { + mutable int *_refCount; + uint32 _capacity; + } _extern; + }; + + inline bool isStorageIntern() const { + return _str == _storage; + } + +public: + /** Construct a new empty string. */ + String() : _size(0), _str(_storage) { _storage[0] = 0; } + + /** Construct a new string from the given NULL-terminated C string. */ + String(const char *str); + + /** Construct a new string containing exactly len characters read from address str. */ + String(const char *str, uint32 len); + + /** Construct a new string containing the characters between beginP (including) and endP (excluding). */ + String(const char *beginP, const char *endP); + + /** Construct a copy of the given string. */ + String(const String &str); + + /** Construct a string consisting of the given character. */ + explicit String(char c); + + ~String(); + + String &operator=(const char *str); + String &operator=(const String &str); + String &operator=(char c); + String &operator+=(const char *str); + String &operator+=(const String &str); + String &operator+=(char c); + + bool operator==(const String &x) const; + bool operator==(const char *x) const; + bool operator!=(const String &x) const; + bool operator!=(const char *x) const; + + bool operator<(const String &x) const; + bool operator<=(const String &x) const; + bool operator>(const String &x) const; + bool operator>=(const String &x) const; + + bool equals(const String &x) const; + bool equalsIgnoreCase(const String &x) const; + int compareTo(const String &x) const; // strcmp clone + int compareToIgnoreCase(const String &x) const; // stricmp clone + + bool equals(const char *x) const; + bool equalsIgnoreCase(const char *x) const; + int compareTo(const char *x) const; // strcmp clone + int compareToIgnoreCase(const char *x) const; // stricmp clone + + bool hasSuffix(const String &x) const; + bool hasSuffix(const char *x) const; + + bool hasPrefix(const String &x) const; + bool hasPrefix(const char *x) const; + + bool contains(const String &x) const; + bool contains(const char *x) const; + bool contains(char x) const; + + inline const char *c_str() const { return _str; } + inline uint size() const { return _size; } + + inline bool empty() const { return (_size == 0); } + char firstChar() const { return (_size > 0) ? _str[0] : 0; } + char lastChar() const { return (_size > 0) ? _str[_size - 1] : 0; } + + char operator[](int idx) const { + assert(_str && idx >= 0 && idx < (int)_size); + return _str[idx]; + } + + /** Remove the last character from the string. */ + void deleteLastChar(); + + /** Remove the character at position p from the string. */ + void deleteChar(uint32 p); + + /** Remove all characters from position p to the p + len. If len = String::npos, removes all characters to the end */ + void erase(uint32 p, uint32 len = npos); + + /** Set character c at position p, replacing the previous character there. */ + void setChar(char c, uint32 p); + + /** Insert character c before position p. */ + void insertChar(char c, uint32 p); + + /** Clears the string, making it empty. */ + void clear(); + + /** Convert all characters in the string to lowercase. */ + void toLowercase(); + + /** Convert all characters in the string to uppercase. */ + void toUppercase(); + + /** + * Removes trailing and leading whitespaces. Uses isspace() to decide + * what is whitespace and what not. + */ + void trim(); + + uint hash() const; + + /** + * Print formatted data into a String object. Similar to sprintf, + * except that it stores the result in (variably sized) String + * instead of a fixed size buffer. + */ + static String format(const char *fmt, ...) GCC_PRINTF(1,2); + + /** + * Print formatted data into a String object. Similar to vsprintf, + * except that it stores the result in (variably sized) String + * instead of a fixed size buffer. + */ + static String vformat(const char *fmt, va_list args); + +public: + typedef char value_type; + /** + * Unsigned version of the underlying type. This can be used to cast + * individual string characters to bigger integer types without sign + * extension happening. + */ + typedef unsigned char unsigned_type; + typedef char * iterator; + typedef const char * const_iterator; + + iterator begin() { + // Since the user could potentially + // change the string via the returned + // iterator we have to assure we are + // pointing to a unique storage. + makeUnique(); + + return _str; + } + + iterator end() { + return begin() + size(); + } + + const_iterator begin() const { + return _str; + } + + const_iterator end() const { + return begin() + size(); + } + +protected: + void makeUnique(); + void ensureCapacity(uint32 new_size, bool keep_old); + void incRefCount() const; + void decRefCount(int *oldRefCount); + void initWithCStr(const char *str, uint32 len); +}; + +// Append two strings to form a new (temp) string +String operator+(const String &x, const String &y); + +String operator+(const char *x, const String &y); +String operator+(const String &x, const char *y); + +String operator+(const String &x, char y); +String operator+(char x, const String &y); + +// Some useful additional comparison operators for Strings +bool operator==(const char *x, const String &y); +bool operator!=(const char *x, const String &y); + +// Utility functions to remove leading and trailing whitespaces +extern char *ltrim(char *t); +extern char *rtrim(char *t); +extern char *trim(char *t); + + +/** + * Returns the last component of a given path. + * + * Examples: + * /foo/bar.txt would return 'bar.txt' + * /foo/bar/ would return 'bar' + * /foo/./bar// would return 'bar' + * + * @param path the path of which we want to know the last component + * @param sep character used to separate path components + * @return The last component of the path. + */ +String lastPathComponent(const String &path, const char sep); + +/** + * Normalize a given path to a canonical form. In particular: + * - trailing separators are removed: /foo/bar/ -> /foo/bar + * - double separators (= empty components) are removed: /foo//bar -> /foo/bar + * - dot components are removed: /foo/./bar -> /foo/bar + * + * @todo remove double dot components: /foo/baz/../bar -> /foo/bar + * + * @param path the path to normalize + * @param sep the separator token (usually '/' on Unix-style systems, or '\\' on Windows based stuff) + * @return the normalized path + */ +String normalizePath(const String &path, const char sep); + + +/** + * Simple DOS-style pattern matching function (understands * and ? like used in DOS). + * Taken from exult/files/listfiles.cc + * + * Token meaning: + * "*": any character, any amount of times. + * "?": any character, only once. + * "#": any decimal digit, only once. + * + * Example strings/patterns: + * String: monkey.s01 Pattern: monkey.s?? => true + * String: monkey.s101 Pattern: monkey.s?? => false + * String: monkey.s99 Pattern: monkey.s?1 => false + * String: monkey.s101 Pattern: monkey.s* => true + * String: monkey.s99 Pattern: monkey.s*1 => false + * String: monkey.s01 Pattern: monkey.s## => true + * String: monkey.s01 Pattern: monkey.### => false + * + * @param str Text to be matched against the given pattern. + * @param pat Glob pattern. + * @param ignoreCase Whether to ignore the case when doing pattern match + * @param pathMode Whether to use path mode, i.e., whether slashes must be matched explicitly. + * + * @return true if str matches the pattern, false otherwise. + */ +bool matchString(const char *str, const char *pat, bool ignoreCase = false, bool pathMode = false); + + +/** + * Take a 32 bit value and turn it into a four character string, where each of + * the four bytes is turned into one character. Most significant byte is printed + * first. + */ +String tag2string(uint32 tag); + +/** + * Copy up to size - 1 characters from src to dst and also zero terminate the + * result. Note that src must be a zero terminated string. + * + * In case size is zero this function just returns the length of the source + * string. + * + * @note This is modeled after OpenBSD's strlcpy. See the manpage here: + * http://www.openbsd.org/cgi-bin/man.cgi?query=strlcpy + * + * @param dst The destination buffer. + * @param src The source string. + * @param size The size of the destination buffer. + * @return The length of the (non-truncated) result, i.e. strlen(src). + */ +size_t strlcpy(char *dst, const char *src, size_t size); + +/** + * Append the string src to the string dst. Note that both src and dst must be + * zero terminated. The result will be zero terminated. At most + * "size - strlen(dst) - 1" bytes will be appended. + * + * In case the dst string does not contain a zero within the first "size" bytes + * the dst string will not be changed and size + strlen(src) is returned. + * + * @note This is modeled after OpenBSD's strlcat. See the manpage here: + * http://www.openbsd.org/cgi-bin/man.cgi?query=strlcat + * + * @param dst The string the source string should be appended to. + * @param src The source string. + * @param size The (total) size of the destination buffer. + * @return The length of the (non-truncated) result. That is + * strlen(dst) + strlen(src). In case strlen(dst) > size + * size + strlen(src) is returned. + */ +size_t strlcat(char *dst, const char *src, size_t size); + +/** + * Convenience wrapper for tag2string which "returns" a C string. + * Note: It is *NOT* safe to do anything with the return value other than directly + * copying or printing it. + */ +#define tag2str(x) Common::tag2string(x).c_str() + + +} // End of namespace Common + +extern int scumm_stricmp(const char *s1, const char *s2); +extern int scumm_strnicmp(const char *s1, const char *s2, uint n); + +#endif diff --git a/dists/scummvm.rc b/dists/scummvm.rc index d76e168f92..fa650dcd9e 100644 --- a/dists/scummvm.rc +++ b/dists/scummvm.rc @@ -71,6 +71,9 @@ toon.dat FILE "dists/engine-data/toon.dat" #if ENABLE_WINTERMUTE == STATIC_PLUGIN wintermute.zip FILE "dists/engine-data/wintermute.zip" #endif +#if ENABLE_XEEN == STATIC_PLUGIN +xeen.ccs FILE "dists/engine-data/xeen.ccs" +#endif #if ENABLE_AGI == STATIC_PLUGIN pred.dic FILE "dists/pred.dic" #endif diff --git a/dists/scummvm.rc.in b/dists/scummvm.rc.in index f84418d057..21cd8a4362 100644 --- a/dists/scummvm.rc.in +++ b/dists/scummvm.rc.in @@ -71,6 +71,9 @@ toon.dat FILE "dists/engine-data/toon.dat" #if ENABLE_WINTERMUTE == STATIC_PLUGIN wintermute.zip FILE "dists/engine-data/wintermute.zip" #endif +#if ENABLE_XEEN == STATIC_PLUGIN +xeen.ccs FILE "dists/engine-data/xeen.ccs" +#endif #if ENABLE_AGI == STATIC_PLUGIN pred.dic FILE "dists/pred.dic" #endif diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index 7fc17a5e84..d98142eacb 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -61,7 +61,7 @@ AttributeCategory XeenItem::getAttributeCategory() const { return (AttributeCategory)idx; } -const char *XeenItem::getItemName(ItemCategory category, uint id) { +const Common::String &XeenItem::getItemName(ItemCategory category, uint id) { if (id < 82) return Res.ITEM_NAMES[category][id]; @@ -294,7 +294,7 @@ Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) { (i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN : "", (i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "", displayNum, - Res.WEAPON_NAMES[i._id], + Res.WEAPON_NAMES[i._id].c_str(), !i._bonusFlags ? "" : Res.BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK], (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || !i._bonusFlags ? "\b " : "" @@ -451,10 +451,10 @@ Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) { 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) ? Res.ITEM_BROKEN : "", - (i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "", + (i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN.c_str() : "", + (i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED.c_str() : "", displayNum, - Res.ARMOR_NAMES[i._id], + Res.ARMOR_NAMES[i._id].c_str(), (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || !i._bonusFlags ? "\b " : "" ); @@ -568,10 +568,10 @@ Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum) 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) ? Res.ITEM_BROKEN : "", - (i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "", + (i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN.c_str() : "", + (i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED.c_str() : "", displayNum, - Res.ARMOR_NAMES[i._id], + Res.ARMOR_NAMES[i._id].c_str(), (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || !i._bonusFlags ? "\b " : "" ); @@ -614,10 +614,10 @@ Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) { 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) ? Res.ITEM_BROKEN : "", - (i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "", + (i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN.c_str() : "", + (i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED.c_str() : "", displayNum, - Res.ARMOR_NAMES[i._id], + Res.ARMOR_NAMES[i._id].c_str(), (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || !i._id ? "\b " : "" ); @@ -993,7 +993,7 @@ int Character::statColor(int amount, int threshold) { int Character::statBonus(uint statValue) const { int idx; - for (idx = 0; Res.STAT_VALUES[idx] <= statValue; ++idx) + for (idx = 0; Res.STAT_VALUES[idx] <= (int)statValue; ++idx) ; return Res.STAT_BONUSES[idx]; diff --git a/engines/xeen/character.h b/engines/xeen/character.h index bf4966c348..480215aa67 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -106,7 +106,7 @@ public: /** * Return the name of the item */ - static const char *getItemName(ItemCategory category, uint id); + static const Common::String &getItemName(ItemCategory category, uint id); public: XeenItem(); @@ -140,7 +140,7 @@ class InventoryItems : public Common::Array<XeenItem> { protected: Character *_character; ItemCategory _category; - const char *const *_names; + const Common::String *_names; XeenEngine *getVm(); void equipError(int itemIndex1, ItemCategory category1, int itemIndex2, diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp index b7a7df8c85..132fbd5a4b 100644 --- a/engines/xeen/dialogs_char_info.cpp +++ b/engines/xeen/dialogs_char_info.cpp @@ -359,7 +359,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) { stat1 = c.getStat((Attribute)attrib, false); stat2 = c.getStat((Attribute)attrib, true); idx = 0; - while (Res.STAT_VALUES[idx] <= stat1) + while (Res.STAT_VALUES[idx] <= (int)stat1) ++idx; msg = Common::String::format(Res.CURRENT_MAXIMUM_RATING_TEXT, Res.STAT_NAMES[attrib], @@ -434,9 +434,9 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) { if (c._skills[skill]) { if (skill == THIEVERY) { lines[0] = Common::String::format("\n\t020%s%u", - Res.SKILL_NAMES[THIEVERY], c.getThievery()); + Res.SKILL_NAMES[THIEVERY].c_str(), c.getThievery()); } else { - lines[skill] = Common::String::format("\n\t020%s", Res.SKILL_NAMES[skill]); + lines[skill] = Common::String::format("\n\t020%s", Res.SKILL_NAMES[skill].c_str()); } } } @@ -446,7 +446,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) { } 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", - Res.STAT_NAMES[attrib], lines[0].c_str(), lines[1].c_str(), + Res.STAT_NAMES[attrib].c_str(), 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(), @@ -505,10 +505,10 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) { if (c._conditions[condition]) { if (condition >= UNCONSCIOUS) { lines[condition] = Common::String::format("\n\t020%s", - Res.CONDITION_NAMES[condition]); + Res.CONDITION_NAMES[condition].c_str()); } else { lines[condition] = Common::String::format("\n\t020%s\t095-%d", - Res.CONDITION_NAMES[condition], c._conditions[condition]); + Res.CONDITION_NAMES[condition].c_str(), c._conditions[condition]); } ++total; @@ -517,7 +517,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", Res.GOOD); + lines[0] = Common::String::format("\n\t020%s", Res.GOOD.c_str()); ++total; } @@ -531,7 +531,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) { lines[19] = Common::String::format(Res.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", - Res.CONSUMABLE_NAMES[3], lines[0].c_str(), lines[1].c_str(), + Res.CONSUMABLE_NAMES[3].c_str(), 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(), diff --git a/engines/xeen/dialogs_create_char.cpp b/engines/xeen/dialogs_create_char.cpp index 73aa4b3f02..c1c6bc8c04 100644 --- a/engines/xeen/dialogs_create_char.cpp +++ b/engines/xeen/dialogs_create_char.cpp @@ -384,7 +384,7 @@ int CreateCharacterDialog::newCharDetails(Race race, Sex sex, int classId, // If a class is provided, set the class name if (classId != -1) { - classStr = Common::String::format("\t062\v168%s", Res.CLASS_NAMES[classId]); + classStr = Common::String::format("\t062\v168%s", Res.CLASS_NAMES[classId].c_str()); } // Set up default skill for the race, if any diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp index c9249f3b74..bbf7fa4ab8 100644 --- a/engines/xeen/dialogs_items.cpp +++ b/engines/xeen/dialogs_items.cpp @@ -1052,7 +1052,7 @@ void ItemsDialog::itemToGold(Character &c, int itemIndex, ItemCategory category, if (category == CATEGORY_WEAPON && item._id == 34) { sound.playFX(21); ErrorScroll::show(_vm, Common::String::format("\v012\t000\x03""c%s", - Res.SPELL_FAILED)); + Res.SPELL_FAILED.c_str())); } else if (item._id != 0) { // There is a valid item present // Calculate cost of item and add it to the party's total diff --git a/engines/xeen/dialogs_quests.cpp b/engines/xeen/dialogs_quests.cpp index 5e5171ea87..73035b3bb9 100644 --- a/engines/xeen/dialogs_quests.cpp +++ b/engines/xeen/dialogs_quests.cpp @@ -91,7 +91,7 @@ void Quests::execute() { case 83: case 84: lines[count++] = Common::String::format("%d %s%c", - party._questItems[idx], Res.QUEST_ITEM_NAMES[idx], + party._questItems[idx], Res.QUEST_ITEM_NAMES[idx].c_str(), party._questItems[idx] == 1 ? ' ' : 's'); break; default: diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index cd31d5b3be..96917e225c 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -345,7 +345,7 @@ const char *SpellsDialog::setSpellText(Character *c, int isCasting) { if (party._mazeId == 49 || party._mazeId == 37) { for (uint spellId = 0; spellId < 76; ++spellId) { int idx = 0; - while (idx < MAX_SPELLS_PER_CLASS && Res.SPELLS_ALLOWED[category][idx] != spellId) + while (idx < MAX_SPELLS_PER_CLASS && Res.SPELLS_ALLOWED[category][idx] != (int)spellId) ++idx; // Handling if the spell is appropriate for the character's class diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index 3d536a4194..2ba3b6f993 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -218,16 +218,25 @@ Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::S /*------------------------------------------------------------------------*/ FileManager::FileManager(XeenEngine *vm) { - Common::File f; _isDarkCc = vm->getGameID() == GType_DarkSide; - - if (vm->getGameID() == GType_Swords) { + File::_xeenCc = File::_darkCc = nullptr; +} + +FileManager::~FileManager() { + SearchMan.remove("intro"); + SearchMan.remove("data"); + delete File::_xeenCc; + delete File::_darkCc; +} + +bool FileManager::setup() { + if (g_vm->getGameID() == GType_Swords) { File::_xeenCc = nullptr; File::_darkCc = new CCArchive("swrd.cc", "xeen", true); } else { - File::_xeenCc = (vm->getGameID() == GType_DarkSide) ? nullptr : + File::_xeenCc = (g_vm->getGameID() == GType_DarkSide) ? nullptr : new CCArchive("xeen.cc", "xeen", true); - File::_darkCc = (vm->getGameID() == GType_Clouds) ? nullptr : + File::_darkCc = (g_vm->getGameID() == GType_Clouds) ? nullptr : new CCArchive("dark.cc", "dark", true); } @@ -236,15 +245,26 @@ FileManager::FileManager(XeenEngine *vm) { SearchMan.add("intro", File::_introCc); } - File::_currentArchive = vm->getGameID() == GType_DarkSide || vm->getGameID() == GType_Swords ? + File::_currentArchive = g_vm->getGameID() == GType_DarkSide || g_vm->getGameID() == GType_Swords ? File::_darkCc : File::_xeenCc; assert(File::_currentArchive); -} -FileManager::~FileManager() { - SearchMan.remove("intro"); - delete File::_xeenCc; - delete File::_darkCc; + // Ensure the custom CC archive is present + File f; + if (!f.exists("xeen.ccs")) { + g_vm->GUIError("Could not find xeen.ccs data file"); + return false; + } + + // Verify the version of the CC is correct + CCArchive *dataCc = new CCArchive("xeen.ccs", "data", true); + if (!f.open("VERSION", *dataCc) || f.readUint32LE() != 1) { + g_vm->GUIError("xeen.ccs is out of date"); + return false; + } + SearchMan.add("data", dataCc); + + return true; } void FileManager::setGameCc(int ccMode) { diff --git a/engines/xeen/files.h b/engines/xeen/files.h index 3a4c4b1054..4ceadcd753 100644 --- a/engines/xeen/files.h +++ b/engines/xeen/files.h @@ -90,6 +90,12 @@ public: ~FileManager(); /** + * Sets up the CC files + * @returns Returns true if the setup was successful + */ + bool setup(); + + /** * Set which game side files to use * @param ccMode 0=Clouds, 1=Dark Side */ diff --git a/engines/xeen/locations.cpp b/engines/xeen/locations.cpp index 7a8290504a..53a1c80c48 100644 --- a/engines/xeen/locations.cpp +++ b/engines/xeen/locations.cpp @@ -69,7 +69,7 @@ int BaseLocation::show() { // Load the needed sprite sets for the location for (uint idx = 0; idx < _townSprites.size(); ++idx) { Common::String shapesName = Common::String::format("%s%d.twn", - Res.TOWN_ACTION_SHAPES[_locationActionId], idx + 1); + Res.TOWN_ACTION_SHAPES[_locationActionId].c_str(), idx + 1); _townSprites[idx].load(shapesName); } diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 8bb04b1eeb..58a294c610 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -38,24 +38,6 @@ 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 }; -const char *const MUSIC_FILES1[5] = { - "outdoors.m", "town.m", "cavern.m", "dungeon.m", "castle.m" -}; - -const char *const MUSIC_FILES2[6][7] = { - { "outday1.m", "outday2.m", "outday4.m", "outnght1.m", - "outnght2.m", "outnght4.m", "daydesrt.m" }, - { "townday1.m", "twnwlk.m", "newbrigh.m", "twnnitea.m", - "twnniteb.m", "twnwlk.m", "townday1.m" }, - { "cavern1.m", "cavern2.m", "cavern3a.m", "cavern1.m", - "cavern2.m", "cavern3a.m", "cavern1.m" }, - { "dngon1.m", "dngon2.m", "dngon3.m", "dngon1.m", - "dngon2.m", "dngon3.m", "dngon1.m" }, - { "cstl1rev.m", "cstl2rev.m", "cstl3rev.m", "cstl1rev.m", - "cstl2rev.m", "cstl3rev.m", "cstl1rev.m" }, - { "sf05.m", "sf05.m", "sf05.m", "sf05.m", "sf05.m", "sf05.m", "sf05.m" } -}; - MonsterStruct::MonsterStruct() { _experience = 0; _hp = 0; @@ -1194,7 +1176,7 @@ void Map::load(int mapId) { if (_vm->_files->_isDarkCc) { int randIndex = _vm->getRandomNumber(6); - musName = MUSIC_FILES2[_mazeData->_wallKind][randIndex]; + musName = Res.MUSIC_FILES2[_mazeData->_wallKind][randIndex]; } else { musName = "outdoors.m"; } @@ -1213,7 +1195,7 @@ void Map::load(int mapId) { if (_mazeData[0]._wallTypes[i] != 0) { _wallSprites._surfaces[i].load(Common::String::format("%s.wal", - Res.OUTDOORS_WALL_TYPES[_mazeData[0]._wallTypes[i]])); + Res.OUTDOORS_WALL_TYPES[_mazeData[0]._wallTypes[i]].c_str())); } _surfaceSprites[i].clear(); @@ -1232,20 +1214,20 @@ void Map::load(int mapId) { _sideMusic = isDarkCc; if (isDarkCc) { int randIndex = _vm->getRandomNumber(6); - musName = MUSIC_FILES2[MUS_INDEXES[_mazeData->_wallKind]][randIndex]; + musName = Res.MUSIC_FILES2[MUS_INDEXES[_mazeData->_wallKind]][randIndex]; } else { - musName = MUSIC_FILES1[MUS_INDEXES[_mazeData->_wallKind]]; + musName = Res.MUSIC_FILES1[MUS_INDEXES[_mazeData->_wallKind]]; } if (musName != sound._currentMusic) sound.playSong(musName, 207); // Load sprite sets needed for scene rendering _skySprites[1].load(Common::String::format("%s.sky", - Res.TERRAIN_TYPES[_mazeData[0]._wallKind])); + Res.TERRAIN_TYPES[_mazeData[0]._wallKind].c_str())); _groundSprites.load(Common::String::format("%s.gnd", - Res.TERRAIN_TYPES[_mazeData[0]._wallKind])); + Res.TERRAIN_TYPES[_mazeData[0]._wallKind].c_str())); _tileSprites.load(Common::String::format("%s.til", - Res.TERRAIN_TYPES[_mazeData[0]._wallKind])); + Res.TERRAIN_TYPES[_mazeData[0]._wallKind].c_str())); for (int i = 0; i < TOTAL_SURFACES; ++i) { _surfaceSprites[i].clear(); @@ -1258,15 +1240,15 @@ void Map::load(int mapId) { _wallSprites._surfaces[i].clear(); _wallSprites._fwl1.load(Common::String::format("f%s1.fwl", - Res.TERRAIN_TYPES[_mazeData[0]._wallKind])); + Res.TERRAIN_TYPES[_mazeData[0]._wallKind].c_str())); _wallSprites._fwl2.load(Common::String::format("f%s2.fwl", - Res.TERRAIN_TYPES[_mazeData[0]._wallKind])); + Res.TERRAIN_TYPES[_mazeData[0]._wallKind].c_str())); _wallSprites._fwl3.load(Common::String::format("f%s3.fwl", - Res.TERRAIN_TYPES[_mazeData[0]._wallKind])); + Res.TERRAIN_TYPES[_mazeData[0]._wallKind].c_str())); _wallSprites._fwl4.load(Common::String::format("f%s4.fwl", - Res.TERRAIN_TYPES[_mazeData[0]._wallKind])); + Res.TERRAIN_TYPES[_mazeData[0]._wallKind].c_str())); _wallSprites._swl.load(Common::String::format("s%s.swl", - Res.TERRAIN_TYPES[_mazeData[0]._wallKind])); + Res.TERRAIN_TYPES[_mazeData[0]._wallKind].c_str())); // Set entries in the indoor draw list to the correct sprites // for drawing various parts of the background diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index dcbc7def44..68bc7685cb 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -720,7 +720,7 @@ void Party::giveTreasureToCharacter(Character &c, ItemCategory category, int ite w.update(); events.ipause(5); - const char *itemName = XeenItem::getItemName(category, treasureItem._id); + const char *itemName = XeenItem::getItemName(category, treasureItem._id).c_str(); w.writeString(Common::String::format(Res.X_FOUND_Y, c._name.c_str(), itemName)); w.update(); events.ipause(5); @@ -817,7 +817,7 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int } for (int idx = 0; idx < 39; ++idx) { - if (Res.SPELLS_ALLOWED[idx2][idx] == takeVal) { + if (Res.SPELLS_ALLOWED[idx2][idx] == (int)takeVal) { ps._spells[idx] = false; break; } @@ -1086,7 +1086,7 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int } for (int idx = 0; idx < 39; ++idx) { - if (Res.SPELLS_ALLOWED[idx2][idx] == giveVal) { + if (Res.SPELLS_ALLOWED[idx2][idx] == (int)giveVal) { ps._spells[idx] = true; intf.spellFX(&ps); break; diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 7048726fad..86dc4413f8 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -30,16 +30,6 @@ namespace Xeen { Resources *g_resources; -Resources *Resources::init(XeenEngine *vm) { - if (vm->getGameID() == GType_Clouds || vm->getGameID() == GType_DarkSide - || vm->getGameID() == GType_WorldOfXeen) - g_resources = new WorldOfXeen::WorldOfXeenResources(); - else - g_resources = new Resources(); - - return g_resources; -} - Resources::Resources() { g_resources = this; g_vm->_files->setGameCc(1); @@ -50,1702 +40,343 @@ Resources::Resources() { while (f.pos() < f.size()) _maeNames.push_back(f.readString()); f.close(); -} - -/*------------------------------------------------------------------------*/ - -const char *const Resources::CREDITS = - "\013""012\010""000\003""c\014""35Designed and Directed By:\n" - "\014""17Jon Van Caneghem\003""l\n" - "\n" - "\t025\014""35Programming:\n" - "\t035\014""17Mark Caldwell\n" - "\t035Dave Hathaway\n" - "\n" - "\t025\014""35Sound System & FX:\n" - "\t035\014""17Mike Heilemann\n" - "\n" - "\t025\014""35Music & Speech:\n" - "\t035\014""17Tim Tully\n" - "\n" - "\t025\014""35Writing:\n" - "\t035\014""17Paul Rattner\n" - "\t035Debbie Van Caneghem\n" - "\t035Jon Van Caneghem\013""012\n" - "\n" - "\n" - "\t180\014""35Graphics:\n" - "\t190\014""17Jonathan P. Gwyn\n" - "\t190Bonita Long-Hemsath\n" - "\t190Julia Ulano\n" - "\t190Ricardo Barrera\n" - "\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\003""c"; - -const char *const Resources::OPTIONS_TITLE = - "\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"; - -const char *const Resources::THE_PARTY_NEEDS_REST = "\x0B""012The Party needs rest!"; - -const char *const Resources::WHO_WILL = "\x03""c\x0B""000\x09""000%s\x0A\x0A" - "Who will\x0A%s?\x0A\x0B""055F1 - F%d"; - -const char *const Resources::HOW_MUCH = "\x3""cHow Much\n\n"; - -const char *const Resources::WHATS_THE_PASSWORD = "What's the Password?"; - -const char *const Resources::IN_NO_CONDITION = "\x0B""007%s is not in any condition to perform actions!"; - -const char *const Resources::NOTHING_HERE = "\x03""c\x0B""010Nothing here."; - -const char *const Resources::TERRAIN_TYPES[6] = { - "town", "cave", "towr", "cstl", "dung", "scfi" -}; - -const char *const Resources::OUTDOORS_WALL_TYPES[16] = { - nullptr, "mount", "ltree", "dtree", "grass", "snotree", "dsnotree", - "snomnt", "dedltree", "mount", "lavamnt", "palm", "dmount", "dedltree", - "dedltree", "dedltree" -}; - -const char *const Resources::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", - "space.srf" -}; - -const char *const Resources::WHO_ACTIONS[32] = { - "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 Resources::WHO_WILL_ACTIONS[4] = { - "Open Grate", "Open Door", "Open Scroll", "Select Char" -}; - -const byte Resources::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 Resources::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 }, -}; - -const char *const Resources::DIRECTION_TEXT_UPPER[4] = { "NORTH", "EAST", "SOUTH", "WEST" }; - -const char *const Resources::DIRECTION_TEXT[4] = { "North", "East", "South", "West" }; - -const char *const Resources::RACE_NAMES[5] = { "Human", "Elf", "Dwarf", "Gnome", "H-Orc" }; - -const int Resources::RACE_HP_BONUSES[5] = { 0, -2, 1, -1, 2 }; - -const int Resources::RACE_SP_BONUSES[5][2] = { - { 0, 0 }, { 2, 0 }, { -1, -1 }, { 1, 1 }, { -2, -2 } -}; - -const char *const Resources::ALIGNMENT_NAMES[3] = { "Good", "Neutral", "Evil" }; - -const char *const Resources::SEX_NAMES[2] = { "Male", "Female" }; - -const char *const Resources::SKILL_NAMES[18] = { - "Thievery\t100", "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 Resources::CLASS_NAMES[11] = { - "Knight", "Paladin", "Archer", "Cleric", "Sorcerer", "Robber", - "Ninja", "Barbarian", "Druid", "Ranger", nullptr -}; - -const uint Resources::CLASS_EXP_LEVELS[10] = { - 1500, 2000, 2000, 1500, 2000, 1000, 1500, 1500, 1500, 2000 -}; - -const char *const Resources::CONDITION_NAMES[17] = { - "Cursed", "Heart Broken", "Weak", "Poisoned", "Diseased", - "Insane", "In Love", "Drunk", "Asleep", "Depressed", "Confused", - "Paralyzed", "Unconscious", "Dead", "Stone", "Eradicated", "Good" -}; - -const int Resources::CONDITION_COLORS[17] = { - 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 6, 6, 6, 6, 15 -}; - -const char *const Resources::GOOD = "Good"; - -const char *const Resources::BLESSED = "\n\t020Blessed\t095%+d"; - -const char *const Resources::POWER_SHIELD = "\n\t020Power Shield\t095%+d"; - -const char *const Resources::HOLY_BONUS = "\n\t020Holy Bonus\t095%+d"; - -const char *const Resources::HEROISM = "\n\t020Heroism\t095%+d"; - -const char *const Resources::IN_PARTY = "\014""15In Party\014""d"; - -const char *const Resources::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 char *const Resources::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 Resources::FACE_CONDITION_FRAMES[17] = { - 2, 2, 2, 1, 1, 4, 4, 4, 3, 2, 4, 3, 3, 5, 6, 7, 0 -}; - -const int Resources::CHAR_FACES_X[6] = { 10, 45, 81, 117, 153, 189 }; - -const int Resources::HP_BARS_X[6] = { 13, 50, 86, 122, 158, 194 }; - -const char *const Resources::NO_ONE_TO_ADVENTURE_WITH = "You have no one to adventure with"; - -const char *const Resources::YOUR_ROSTER_IS_FULL = "Your Roster is full!"; - -const byte Resources::DARKNESS_XLAT[3][256] = { - { - 0, 25, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 60, 61, 62, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 76, 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 108, 109, 110, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 124, 125, 126, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 140, 141, 142, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 168, 169, 170, 171, 172, 173, 174, 175, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 188, 189, 190, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 204, 205, 206, 207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 220, 221, 222, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 236, 237, 238, 239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 252, 253, 254, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }, { - 0, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 40, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, - 56, 57, 58, 59, 60, 61, 62, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 72, 73, 74, 75, 76, 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, - 88, 89, 90, 91, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, - 104, 105, 106, 107, 108, 109, 110, 111, 0, 0, 0, 0, 0, 0, 0, 0, - 120, 121, 122, 123, 124, 125, 126, 127, 0, 0, 0, 0, 0, 0, 0, 0, - 136, 137, 138, 139, 140, 141, 142, 143, 0, 0, 0, 0, 0, 0, 0, 0, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 184, 185, 186, 187, 188, 189, 190, 191, 0, 0, 0, 0, 0, 0, 0, 0, - 200, 201, 202, 203, 204, 205, 206, 207, 0, 0, 0, 0, 0, 0, 0, 0, - 216, 217, 218, 219, 220, 221, 222, 223, 0, 0, 0, 0, 0, 0, 0, 0, - 232, 233, 234, 235, 236, 237, 238, 239, 0, 0, 0, 0, 0, 0, 0, 0, - 248, 249, 250, 251, 252, 253, 254, 255, 0, 0, 0, 0, 0, 0, 0, 0 - }, { - 0, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 0, 0, 0, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 0, 0, 0, 0, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 0, 0, 0, 0, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 0, 0, 0, 0, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 0, 0, 0, 0, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 0, 0, 0, 0, - 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 0, 0, 0, 0, 0, 0, 0, 0, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 0, 0, 0, 0, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 0, 0, 0, 0, - 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 0, 0, 0, 0, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 0, 0, 0, 0, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 0, 0, 0, 0 - } -}; - -const char *const Resources::PLEASE_WAIT = "\014""d\003""c\011""000" - "\013""002Please Wait..."; - -const char *const Resources::OOPS = "\003""c\011""000\013""002Oops..."; - -const int8 Resources::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 Resources::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 Resources::MONSTER_GRID_BITMASK[12] = { - 0xC, 8, 4, 0, 0xF, 0xF000, 0xF00, 0xF0, 0xF00, 0xF0, 0x0F, 0xF000 -}; - -const int Resources::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 Resources::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 } -}; - -const int Resources::INDOOR_MONSTERS_Y[4] = { 2, 34, 53, 59 }; - -const int Resources::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 Resources::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 Resources::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 Resources::DIRECTION_ANIM_POSITIONS[4][4] = { - { 0, 1, 2, 3 }, { 3, 0, 1, 2 }, { 2, 3, 0, 1 }, { 1, 2, 3, 0 } -}; - -const byte Resources::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, - 0, 12, 0, 12, 8, 12, 8, 12, 8, 12, 8, 12, - 0, 0, 0, 0, 8, 8, 8, 8, 0, 0, 4, 4 - }, { - 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 - }, { - 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, 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 - } -}; - -const int Resources::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 Resources::DRAW_FRAMES[25][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 } -}; - -const int Resources::COMBAT_FLOAT_X[8] = { -2, -1, 0, 1, 2, 1, 0, -1 }; - -const int Resources::COMBAT_FLOAT_Y[8] = { -2, 0, 2, 0, -1, 0, 2, 0 }; - -const int Resources::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 } -}; - -const uint Resources::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 - } -}; - -const int Resources::BASE_HP_BY_CLASS[10] = { 10, 8, 7, 5, 4, 8, 7, 12, 6, 9 }; - -const int Resources::AGE_RANGES[10] = { 1, 6, 11, 18, 36, 51, 76, 101, 201, 0xffff }; - -const int Resources::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 uint Resources::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, -}; - -const int Resources::STAT_BONUSES[24] = { - -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20 -}; - -const int Resources::ELEMENTAL_CATEGORIES[6] = { 8, 15, 20, 25, 33, 36 }; - -const int Resources::ATTRIBUTE_CATEGORIES[10] = { - 9, 17, 25, 33, 39, 45, 50, 56, 61, 72 }; - -const int Resources::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 Resources::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 Resources::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 Resources::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 Resources::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 Resources::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 Resources::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 Resources::METAL_LAC[9] = { -3, 0, -2, -1, 1, 2, 4, 6, 8 }; - -const int Resources::ARMOR_STRENGTHS[14] = { 0, 2, 4, 5, 6, 7, 8, 10, 4, 2, 1, 1, 1, 1 }; - -const int Resources::MAKE_ITEM_ARR1[6] = { 0, 8, 15, 20, 25, 33 }; - -const int Resources::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 Resources::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 Resources::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 Resources::MAKE_ITEM_ARR5[8][2] = { - { 0, 0 }, { 1, 15 }, { 16, 30 }, { 31, 40 }, { 41, 50 }, - { 51, 60 }, { 61, 73 }, { 61, 73 } -}; - -const int Resources::OUTDOOR_DRAWSTRUCT_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 -}; - -const int Resources::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 Resources::TOWN_ACTION_MUSIC[2][7] = { - { "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 Resources::TOWN_ACTION_SHAPES[7] = { - "bnkr", "blck", "gild", "tvrn", "tmpl", "trng", "eface08" -}; - -const int Resources::TOWN_ACTION_FILES[2][7] = { - { 3, 2, 4, 2, 4, 2, 1 }, { 5, 3, 7, 5, 4, 6, 1 } -}; - -const char *const Resources::BANK_TEXT = "\xD\x2\x3""c\xB""122\t013" - "\xC""37D\xC""dep\t040\xC""37W\xC""dith\t067ESC" - "\x1\t000\xB""000Bank of Xeen\xB""015\n" - "Bank\x3l\n" - "Gold\x3r\t000%s\x3l\n" - "Gems\x3r\t000%s\x3""c\n" - "\n" - "Party\x3l\n" - "Gold\x3r\t000%s\x3l\n" - "Gems\x3r\t000%s"; - -const char *const Resources::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 Resources::GUILD_NOT_MEMBER_TEXT = - "\n\nYou have to be a member to shop here."; - -const char *const Resources::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 Resources::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 Resources::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 Resources::GOOD_STUFF = "\n" - "\n" - "Good Stuff\n" - "\n" - "Hit a key!"; - -const char *const Resources::HAVE_A_DRINK = "\n\nHave a Drink\n\nHit a key!"; - -const char *const Resources::YOURE_DRUNK = "\n\nYou're Drunk\n\nHit a key!"; - -const int Resources::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 Resources::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 Resources::EXPERIENCE_FOR_LEVEL = - "%s needs %lu experience for level %u."; - -const char *const Resources::LEARNED_ALL = "%s has learned all we can teach!"; - -const char *const Resources::ELIGIBLE_FOR_LEVEL = "%s is eligible for level %d."; - -const char *const Resources::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"; - -const char *const Resources::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 Resources::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 Resources::DEPOSIT_WITHDRAWL[2] = { "Deposit", "Withdrawl" }; - -const char *const Resources::NOT_ENOUGH_X_IN_THE_Y = - "\x03""c\x0B""012Not enough %s in the %s!\x03l"; - -const char *const Resources::NO_X_IN_THE_Y = "\x03""c\x0B""012No %s in the %s!\x03l"; - -const char *const Resources::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 Resources::CONSUMABLE_NAMES[4] = { "Gold", "Gems", "Food", "Condition" }; - -const char *const Resources::WHERE_NAMES[2] = { "Party", "Bank" }; - -const char *const Resources::AMOUNT = "\x03""c\x09""000\x0B""051Amount\x03l\n"; - -const char *const Resources::FOOD_PACKS_FULL = "\v007Your food packs are already full!"; - -const char *const Resources::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 Resources::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 Resources::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 Resources::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 Resources::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 Resources::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 uint Resources::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 Resources::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 -}; - -const char *const Resources::NOT_A_SPELL_CASTER = "Not a spell caster..."; - -const char *const Resources::SPELLS_FOR = "\xD\xC""d%s\x2\x3""c\x9""000\xB""002Spells for %s"; - -const char *const Resources::SPELL_LINES_0_TO_9 = - "\x2\x3l\xB""015\x9""0011\n2\n3\n4\n5\n6\n7\n8\n9\n0"; - -const char *const Resources::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 Resources::SPELL_PTS = "Spell Pts"; -const char *const Resources::GOLD = "Gold"; + // Set up items array to map to the names of items in each category + ITEM_NAMES[CATEGORY_WEAPON] = &WEAPON_NAMES[0]; + ITEM_NAMES[CATEGORY_ARMOR] = &ARMOR_NAMES[0]; + ITEM_NAMES[CATEGORY_ACCESSORY] = &ACCESSORY_NAMES[0]; + ITEM_NAMES[CATEGORY_MISC] = &MISC_NAMES[0]; -const char *const Resources::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 Resources::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 Resources::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 Resources::LIGHT_COUNT_TEXT = "\x3l\n\n\t024Light\x3r\t124%d"; - -const char *const Resources::FIRE_RESISTENCE_TEXT = "%c%sFire%s%u"; - -const char *const Resources::ELECRICITY_RESISTENCE_TEXT = "%c%sElectricity%s%u"; - -const char *const Resources::COLD_RESISTENCE_TEXT = "c%sCold%s%u"; - -const char *const Resources::POISON_RESISTENCE_TEXT = "%c%sPoison/Acid%s%u"; - -const char *const Resources::CLAIRVOYANCE_TEXT = "%c%sClairvoyance%s"; - -const char *const Resources::LEVITATE_TEXT = "%c%sLevitate%s"; - -const char *const Resources::WALK_ON_WATER_TEXT = "%c%sWalk on Water"; - -const char *const Resources::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 Resources::WORLD_GAME_TEXT = "World"; -const char *const Resources::DARKSIDE_GAME_TEXT = "Darkside"; -const char *const Resources::CLOUDS_GAME_TEXT = "Clouds"; -const char *const Resources::SWORDS_GAME_TEXT = "Swords"; - -const char *const Resources::WEEK_DAY_STRINGS[10] = { - "Ten", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine" -}; - -const char *const Resources::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 Resources::PARTY_GOLD = "Party Gold"; - -const char *const Resources::PLUS_14 = "14+"; - -const char *const Resources::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 Resources::EXCHANGING_IN_COMBAT = "\x3""c\xB""007\x9""000Exchanging in combat is not allowed!"; - -const char *const Resources::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 Resources::CURRENT_MAXIMUM_TEXT = "\x2\x3""c%s\n" - "Current / Maximum\n" - "\x3r\x9""054%u\x3l\x9""058/ %u"; - -const char *const Resources::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 Resources::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 Resources::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 Resources::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 Resources::NONE = "\n\x9""020"; - -const char *const Resources::EXPERIENCE_TEXT = "\x2\x3""c%s\x3l\n" - "\x9""010Current:\x9""070%lu\n" - "\x9""010Next Level:\x9""070%s\x1"; - -const char *const Resources::ELIGIBLE = "\xC""12Eligible\xC""d"; - -const char *const Resources::IN_PARTY_IN_BANK = - "\x2\x3""cParty %s\n" - "%lu on hand\n" - "%lu in bank\x1\x3l"; - -const char *const Resources::FOOD_TEXT = - "\x2\x3""cParty %s\n" - "%u on hand\n" - "Enough for %u day%s\x3l"; - -const char *const Resources::EXCHANGE_WITH_WHOM = "\t010\v005Exchange with whom?"; - -const char *const Resources::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 Resources::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"; - -const uint Resources::BLACKSMITH_MAP_IDS[2][4] = { { 28, 30, 73, 49 }, { 29, 31, 37, 43 } }; - -const char *const Resources::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"; -const char *const Resources::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 Resources::ITEMS_DIALOG_LINE1 = "\x3r\f%02u\f023%2d)\x3l\t028%s\n"; -const char *const Resources::ITEMS_DIALOG_LINE2 = "\x3r\f%02u\t023%2d)\x3l\t028%s\x3r\t000%lu\n"; - -const char *const Resources::BTN_BUY = "\f37B\fduy"; -const char *const Resources::BTN_SELL = "\f37S\fdell"; -const char *const Resources::BTN_IDENTIFY = "\f37I\fddentify"; -const char *const Resources::BTN_FIX = "\f37F\fdix"; -const char *const Resources::BTN_USE = "\f37U\fdse"; -const char *const Resources::BTN_EQUIP = "\f37E\fdquip"; -const char *const Resources::BTN_REMOVE = "\f37R\fdem"; -const char *const Resources::BTN_DISCARD = "\f37D\fdisc"; -const char *const Resources::BTN_QUEST = "\f37Q\fduest"; -const char *const Resources::BTN_ENCHANT = "E\fdnchant"; -const char *const Resources::BTN_RECHARGE = "R\fdechrg"; -const char *const Resources::BTN_GOLD = "G\fdold"; - -const char *const Resources::ITEM_BROKEN = "\f32broken "; -const char *const Resources::ITEM_CURSED = "\f09cursed "; -const char *const Resources::BONUS_NAMES[7] = { - "", "Dragon Slayer", "Undead Eater", "Golem Smasher", - "Bug Zapper", "Monster Masher", "Beast Bopper" -}; - -const char *const Resources::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 Resources::ARMOR_NAMES[14] = { - nullptr, "robes ", "sale armor ", "ring mail ", "chain mail ", - "splint mail ", "plate mail ", "plate armor ", "shield ", - "helm ", "boots ", "cloak ", "cape ", "gauntlets " -}; - -const char *const Resources::ACCESSORY_NAMES[11] = { - nullptr, "ring ", "belt ", "broach ", "medal ", "charm ", "cameo ", - "scarab ", "pendant ", "necklace ", "amulet " -}; - -const char *const Resources::MISC_NAMES[22] = { - nullptr, "rod ", "jewel ", "gem ", "box ", "orb ", "horn ", "coin ", - "wand ", "whistle ", "potion ", "scroll ", "RogueVM", - "bogusg", "bogus", "bogus", "bogus", "bogus", - "bogus", "bogus", "bogus", "bogus" -}; - -const char *const *Resources::ITEM_NAMES[4] = { - &Resources::WEAPON_NAMES[0], &Resources::ARMOR_NAMES[0], - &Resources::ACCESSORY_NAMES[0], &Resources::MISC_NAMES[0] -}; - -const char *const Resources::ELEMENTAL_NAMES[6] = { - "Fire", "Elec", "Cold", "Acid/Poison", "Energy", "Magic" -}; - -const char *const Resources::ATTRIBUTE_NAMES[10] = { - "might", "Intellect", "Personality", "Speed", "accuracy", "Luck", - "Hit Points", "Spell Points", "Armor Class", "Thievery" -}; - -const char *const Resources::EFFECTIVENESS_NAMES[7] = { - nullptr, "Dragons", "Undead", "Golems", "Bugs", "Monsters", "Beasts" -}; - -const char *const Resources::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)", - "", - "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 Resources::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 Resources::ARMOR_BASE_COSTS[14] = { - 0, 20, 100, 200, 400, 600, 1000, 2000, 100, 60, 40, 250, 200, 100 -}; -const int Resources::ACCESSORY_BASE_COSTS[11] = { - 0, 100, 100, 250, 100, 50, 300, 200, 500, 1000, 2000 -}; -const int Resources::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 Resources::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 Resources::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 Resources::ITEM_SKILL_DIVISORS[4] = { 1, 2, 100, 10 }; - -const int Resources::RESTRICTION_OFFSETS[4] = { 0, 35, 49, 60 }; - -const int Resources::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 Resources::NOT_PROFICIENT = - "\t000\v007\x3""c%ss are not proficient with a %s!"; - -const char *const Resources::NO_ITEMS_AVAILABLE = "\x3""c\n" - "\t000No items available."; - -const char *const Resources::CATEGORY_NAMES[4] = { "Weapons", "Armor", "Accessories", "Miscellaneous" }; - -const char *const Resources::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 Resources::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 Resources::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 Resources::FMT_CHARGES = "\x3rr\t000Charges\x3l"; - -const char *const Resources::AVAILABLE_GOLD_COST = - "\x1\fd\r\x3l\v000\t000Available %s\t150Gold - %lu\x3r\t000Cost" - "\x3l\v011\x2%s%s%s%s%s%s%s%s%s\x1\xC""d"; - -const char *const Resources::CHARGES = "Charges"; - -const char *const Resources::COST = "Cost"; - -const char *const Resources::ITEM_ACTIONS[7] = { - "Equip", "Remove", "Use", "Discard", "Enchant", "Recharge", "Gold" -}; -const char *const Resources::WHICH_ITEM = "\t010\v005%s which item?"; - -const char *const Resources::WHATS_YOUR_HURRY = "\v007What's your hurry?\n" - "Wait till you get out of here!"; - -const char *const Resources::USE_ITEM_IN_COMBAT = - "\v007To use an item in Combat, invoke the Use command on your turn!"; - -const char *const Resources::NO_SPECIAL_ABILITIES = "\v005\x3""c%s\fdhas no special abilities!"; - -const char *const Resources::CANT_CAST_WHILE_ENGAGED = "\x3""c\v007Can't cast %s while engaged!"; - -const char *const Resources::EQUIPPED_ALL_YOU_CAN = "\x3""c\v007You have equipped all the %ss you can!"; -const char *const Resources::REMOVE_X_TO_EQUIP_Y = "\x3""c\v007You must remove %sto equip %s\x8!"; -const char *const Resources::RING = "ring"; -const char *const Resources::MEDAL = "medal"; - -const char *const Resources::CANNOT_REMOVE_CURSED_ITEM = "\x3""You cannot remove a cursed item!"; - -const char *const Resources::CANNOT_DISCARD_CURSED_ITEM = "\3x""cYou cannot discard a cursed item!"; - -const char *const Resources::PERMANENTLY_DISCARD = "\v000\t000\x03lPermanently discard %s\fd?"; - -const char *const Resources::BACKPACK_IS_FULL = "\v005\x3""c\fd%s's backpack is full."; - -const char *const Resources::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 Resources::BUY_X_FOR_Y_GOLD = "\x3l\v000\t000\fdBuy %s\fd for %lu gold?"; - -const char *const Resources::SELL_X_FOR_Y_GOLD = "\x3l\v000\t000\fdSell %s\fd for %lu gold?"; - -const char *const Resources::NO_NEED_OF_THIS = "\v005\x3""c\fdWe have no need of this %s\f!"; - -const char *const Resources::NOT_RECHARGABLE = "\v012\x3""c\fdNot Rechargeable. %s"; - -const char *const Resources::NOT_ENCHANTABLE = "\v012\t000\x3""cNot Enchantable. %s"; - -const char *const Resources::SPELL_FAILED = "Spell Failed!"; - -const char *const Resources::ITEM_NOT_BROKEN = "\fdThat item is not broken!"; - -const char *const Resources::FIX_IDENTIFY[2] = { "Fix", "Identify" }; - -const char *const Resources::FIX_IDENTIFY_GOLD = "\x3l\v000\t000%s %s\fd for %lu gold?"; - -const char *const Resources::IDENTIFY_ITEM_MSG = "\fd\v000\t000\x3""cIdentify Item\x3l\n" - "\n" - "\v012%s\fd\n" - "\n" - "%s"; - -const char *const Resources::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 Resources::ALL = "All"; -const char *const Resources::FIELD_NONE = "None"; -const char *const Resources::DAMAGE_X_TO_Y = "%d to %d"; -const char *const Resources::ELEMENTAL_XY_DAMAGE = "%+d %s Damage"; -const char *const Resources::ATTR_XY_BONUS = "%+d %s"; -const char *const Resources::EFFECTIVE_AGAINST = "x3 vs %s"; - -const char *const Resources::QUESTS_DIALOG_TEXT = - "\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 Resources::CLOUDS_OF_XEEN_LINE = "\b \b*-- \f04Clouds of Xeen\fd --"; -const char *const Resources::DARKSIDE_OF_XEEN_LINE = "\b \b*-- \f04Darkside of Xeen\fd --"; - -const char *const Resources::NO_QUEST_ITEMS = - "\r\x3""c\v000 000Quest Items\x3l\x2\n" - "\n" - "\x3""cNo Quest Items"; -const char *const Resources::NO_CURRENT_QUESTS = - "\x3""c\v000\t000\n" - "\n" - "No Current Quests"; -const char *const Resources::NO_AUTO_NOTES = "\x3""cNo Auto Notes"; - -const char *const Resources::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 Resources::CURRENT_QUESTS_DATA = - "\r\x1\fd\x3""c\t000\v000Current Quests\x3l\x2\n" - "%s\n" - "\n" - "%s\n" - "\n" - "%s"; -const char *const Resources::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"; - -const char *const Resources::REST_COMPLETE = - "\v000\t0008 hours pass. Rest complete.\n" - "%s\n" - "%d food consumed."; -const char *const Resources::PARTY_IS_STARVING = "\f07The Party is Starving!\fd"; -const char *const Resources::HIT_SPELL_POINTS_RESTORED = "Hit Pts and Spell Pts restored."; -const char *const Resources::TOO_DANGEROUS_TO_REST = "Too dangerous to rest here!"; -const char *const Resources::SOME_CHARS_MAY_DIE = "Some Chars may die. Rest anyway?"; - -const char *const Resources::CANT_DISMISS_LAST_CHAR = "You cannot dismiss your last character!"; - -const char *const Resources::REMOVE_DELETE[2] = { "Remove", "Delete" }; - -const char *const Resources::REMOVE_OR_DELETE_WHICH = "\x3l\t010\v005%s which character?"; - -const char *const Resources::YOUR_PARTY_IS_FULL = "\v007Your party is full!"; - -const char *const Resources::HAS_SLAYER_SWORD = - "\v000\t000This character has the Xeen Slayer Sword and cannot be deleted!"; -const char *const Resources::SURE_TO_DELETE_CHAR = - "Are you sure you want to delete %s the %s?"; - -const char *const Resources::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 Resources::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 char *const Resources::NAME_FOR_NEW_CHARACTER = - "\x3""cEnter a Name for this Character\n\n"; -const char *const Resources::SELECT_CLASS_BEFORE_SAVING = - "\v006\x3""cSelect a Class before saving.\x3l"; -const char *const Resources::EXCHANGE_ATTR_WITH = "Exchange %s with..."; - -const int Resources::NEW_CHAR_SKILLS[10] = { 1, 5, -1, -1, 4, 0, 0, -1, 6, 11 }; -const int Resources::NEW_CHAR_SKILLS_LEN[10] = { 11, 8, 0, 0, 12, 8, 8, 0, 9, 11 }; -const int Resources::NEW_CHAR_RACE_SKILLS[10] = { 14, -1, 17, 16, -1, 0, 0, 0, 0, 0 }; - -const int Resources::RACE_MAGIC_RESISTENCES[5] = { 7, 5, 20, 0, 0 }; -const int Resources::RACE_FIRE_RESISTENCES[5] = { 7, 0, 2, 5, 10 }; -const int Resources::RACE_ELECTRIC_RESISTENCES[5] = { 7, 0, 2, 5, 10 }; -const int Resources::RACE_COLD_RESISTENCES[5] = { 7, 0, 2, 5, 10 }; -const int Resources::RACE_ENERGY_RESISTENCES[5] = { 7, 5, 2, 5, 0 }; -const int Resources::RACE_POISON_RESISTENCES[5] = { 7, 0, 2, 20, 0 }; -const int Resources::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 } -}; - -const char *const Resources::COMBAT_DETAILS = "\r\f00\x3""c\v000\t000\x2""Combat%s%s%s\x1"; - -const char *Resources::NOT_ENOUGH_TO_CAST = "\x3""c\v010Not enough %s to Cast %s"; -const char *Resources::SPELL_CAST_COMPONENTS[2] = { "Spell Points", "Gems" }; - -const char *const Resources::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"; - -const char *const Resources::PARTY_FOUND = - "\x3""cThe Party Found:\n" - "\n" - "\x3r\t000%lu Gold\n" - "%lu Gems"; - -const char *const Resources::BACKPACKS_FULL_PRESS_KEY = - "\v007\f12Warning! BackPacks Full!\fd\n" - "Press a Key"; - -const char *const Resources::HIT_A_KEY = "\x3l\v120\t000\x4""077\x3""c\f37Hit a key\xC""d"; - -const char *const Resources::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 Resources::X_FOUND_Y = "\v060\t000\x3""c%s found: %s"; - -const char *const Resources::ON_WHO = "\x3""c\v009On Who?"; - -const char *const Resources::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 Resources::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 Resources::DETECT_MONSTERS = "\x3""cDetect Monsters"; - -const char *const Resources::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"; - -const char *const Resources::HOW_MANY_SQUARES = "\x3""cTeleport\nHow many squares %s (1-9)"; - -const char *const Resources::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 Resources::TOWN_MAP_NUMBERS[2][5] = { - { 28, 29, 30, 31, 32 }, { 29, 31, 33, 35, 37 } -}; - -const char *const Resources::MONSTER_DETAILS = - "\x3l\n" - "%s\x3""c\t100%s\t140%u\t180%u\x3r\t000%s"; - -const char *const Resources::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 Resources::IDENTIFY_MONSTERS = - "Name\x3""c\t100HP\t140AC\t177#Atks\x3r\t000Special%s%s%s"; - -const char *const Resources::EVENT_SAMPLES[6] = { - "ahh.voc", "whereto.voc", "gulp.voc", "null.voc", "scream.voc", "laff1.voc" -}; - -const char *const Resources::MOONS_NOT_ALIGNED = -"\x3""c\xB""012\t000The moons are not aligned. Passage to the %s is unavailable"; - -const char *const Resources::AWARDS_FOR = - "\r\x1\fd\x3""c\v000\t000Awards for %s the %s\x3""l\x2\n" - "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\x1"; - -const char *const Resources::AWARDS_TEXT = - "\r\x2\x3""c\xB""021\t221\xC""37U\xC""dp\t255\xC""37D\xC""down\t289Exit"; - -const char *const Resources::NO_AWARDS = "\x3""cNo Awards"; - -const char *const Resources::WARZONE_BATTLE_MASTER = "The Warzone\n\t125Battle Master"; - -const char *const Resources::WARZONE_MAXED = "What! You again? Go pick on someone your own size!"; - -const char *const Resources::WARZONE_LEVEL = "What level of monsters? (1-10)\n"; - -const char *const Resources::WARZONE_HOW_MANY = "How many monsters? (1-20)\n"; - -const char *const Resources::PICKS_THE_LOCK = "\x3""c\xB""010%s picks the lock!\nPress any key."; - -const char *const Resources::UNABLE_TO_PICK_LOCK = "\x3""c\v010%s was unable to pick the lock!\nPress any key."; - -const char *const Resources::CONTROL_PANEL_TEXT = - "\x1\xC""00\x3""c\xB""000\t000Control Panel\x3r" - "\xB""022\t045\xC""06L\xC""doad:\t124\xC""06E\xC""dfx:" - "\xB""041\t045\xC""06S\xC""dave:\t124\xC""06M\xC""dusic:" - "\xB""060\t045\xC""06Q\xC""duit:" - "\xB""080\t084Mr \xC""06W\xC""dizard:%s\t000\x1"; -const char *const Resources::CONTROL_PANEL_BUTTONS = - "\x3""c\f11" - "\xB""022\t062load\t141%s" - "\xB""041\t062save\t141%s" - "\xB""060\t062exit" - "\xB""079\t102Help\xC""d"; -const char *const Resources::ON = "\f15on\f11"; -const char *const Resources::OFF = "\f32off\f11"; -const char *const Resources::CONFIRM_QUIT = "Are you sure you want to quit?"; -const char *const Resources::MR_WIZARD = - "Are you sure you want Mr.Wizard's Help ?"; -const char *const Resources::NO_LOADING_IN_COMBAT = - "No Loading Allowed in Combat!"; -const char *const Resources::NO_SAVING_IN_COMBAT = - "No Saving Allowed in Combat!"; -const char *const Resources::QUICK_FIGHT_TEXT = "\r\fd\x3""c\v000\t000QuickFight Options\n\n" - "%s\x3l\n\n" - "Current\x3r\n" - "\t000%s\x2\x3""c\v122\t021\f37N\f04ext\t060Exit\x1"; -const char *const Resources::QUICK_FIGHT_OPTIONS[4] = { "Attack", "Cast", "Block", "Run" }; - -const char *const Resources::WORLD_END_TEXT[9] = { - "\n\n\n\n\n\n\n" - "Congratulations Adventurers!\n\n" - "Let the unification ceremony begin!", - "And so the call went out to the people throughout the lands of Xeen" - " that the prophecy was nearing completion.", - "They came in great numbers to witness the momentous occasion.", - "\xB""026The Dragon Pharoah presided over the ceremony.", - "\xB""026Queen Kalindra presented the Cube of Power.", - "\xB""026Prince Roland presented the Xeen Sceptre.", - "\xB""026Together, they placed the Cube of Power...", - "\xB""026and the Sceptre, onto the Altar of Joining.", - "With the prophecy complete, the two sides of Xeen were united as one", -}; + // Load the data from the resource + loadData(); +} -const char *const Resources::WORLD_CONGRATULATIONS = - "\x3""cCongratulations\n\n" - "Your Final Score is:\n\n" - "%010lu\n" - "\x3l\n" - "Please send this score to the Ancient's Headquarters where " - "you'll be added to the Hall of Legends!\n\n" - "Ancient's Headquarters\n" - "New World Computing, Inc.\n" - "P.O. Box 4302\n" - "Hollywood, CA 90078"; -const char *const Resources::WORLD_CONGRATULATIONS2 = - "\n\n\n\n\n\n" - "But wait... there's more!\n" - "\n\n" - "Include the message\n" - "\"%s\"\n" - "with your final score and receive a special bonus."; -const char *const Resources::CLOUDS_CONGRATULATIONS1 = - "\xC""23\x3l" - "\xB""000\t000Please send this score to the Ancient's Headquarters " - "where you'll be added to the Hall of Legends!\xC""33\x3""c" - "\xB""070\t000Press a Key"; -const char *const Resources::CLOUDS_CONGRATULATIONS2 = - "\xC""23\x3l" - "\xB""000\t000Ancient's Headquarters\n" - "New World Computing, Inc.\n" - "P.O. Box 4302\n" - "Hollywood, CA 90078-4302\xC""33\x3""c" - "\xB""070\t000Press a Key"; -const char *const Resources::GOOBER[3] = { - "", "I am a Goober!", "I am a Super Goober!" -}; +void Resources::loadData() { + ResFile file; + file.syncString(CREDITS); + file.syncString(OPTIONS_TITLE); + file.syncString(THE_PARTY_NEEDS_REST); + file.syncString(WHO_WILL); + file.syncString(HOW_MUCH); + file.syncString(WHATS_THE_PASSWORD); + file.syncString(IN_NO_CONDITION); + file.syncString(NOTHING_HERE); + file.syncStrings(TERRAIN_TYPES, 6); + file.syncStrings(OUTDOORS_WALL_TYPES, 16); + file.syncStrings(SURFACE_NAMES, 16); + file.syncStrings(WHO_ACTIONS, 32); + file.syncStrings(WHO_WILL_ACTIONS, 4); + file.syncBytes2D((byte *)SYMBOLS, 20, 64); + file.syncBytes2D((byte *)TEXT_COLORS, 40, 4); + file.syncStrings(DIRECTION_TEXT_UPPER, 4); + file.syncStrings(DIRECTION_TEXT, 4); + file.syncStrings(RACE_NAMES, 5); + file.syncNumbers(RACE_HP_BONUSES, 5); + file.syncNumbers2D((int *)RACE_SP_BONUSES, 5, 2); + file.syncStrings(CLASS_NAMES, 11); + file.syncNumbers(CLASS_EXP_LEVELS, 10); + file.syncStrings(ALIGNMENT_NAMES, 3); + file.syncStrings(SEX_NAMES, 2); + file.syncStrings(SKILL_NAMES, 18); + file.syncStrings(CONDITION_NAMES, 17); + file.syncNumbers(CONDITION_COLORS, 17); + file.syncString(GOOD); + file.syncString(BLESSED); + file.syncString(POWER_SHIELD); + file.syncString(HOLY_BONUS); + file.syncString(HEROISM); + file.syncString(IN_PARTY); + file.syncString(PARTY_DETAILS); + file.syncString(PARTY_DIALOG_TEXT); + file.syncNumbers(FACE_CONDITION_FRAMES, 17); + file.syncNumbers(CHAR_FACES_X, 6); + file.syncNumbers(HP_BARS_X, 6); + file.syncString(NO_ONE_TO_ADVENTURE_WITH); + file.syncBytes2D((byte *)DARKNESS_XLAT, 3, 256); + file.syncString(YOUR_ROSTER_IS_FULL); + file.syncString(PLEASE_WAIT); + file.syncString(OOPS); + file.syncNumbers2D((int *)SCREEN_POSITIONING_X, 4, 48); + file.syncNumbers2D((int *)SCREEN_POSITIONING_Y, 4, 48); + file.syncNumbers(MONSTER_GRID_BITMASK, 12); + file.syncNumbers2D((int *)INDOOR_OBJECT_X, 2, 12); + file.syncNumbers2D((int *)MAP_OBJECT_Y, 2, 12); + file.syncNumbers(INDOOR_MONSTERS_Y, 4); + file.syncNumbers2D((int *)OUTDOOR_OBJECT_X, 2, 12); + file.syncNumbers(OUTDOOR_MONSTER_INDEXES, 26); + file.syncNumbers(OUTDOOR_MONSTERS_Y, 26); + file.syncNumbers2D((int *)DIRECTION_ANIM_POSITIONS, 4, 4); + file.syncBytes2D((byte *)WALL_SHIFTS, 4, 48); + file.syncNumbers(DRAW_NUMBERS, 25); + file.syncNumbers2D((int *)DRAW_FRAMES, 25, 2); + file.syncNumbers(COMBAT_FLOAT_X, 8); + file.syncNumbers(COMBAT_FLOAT_Y, 8); + file.syncNumbers2D((int *)MONSTER_EFFECT_FLAGS, 15, 8); + file.syncNumbers2D((int *)SPELLS_ALLOWED, 3, 40); + file.syncNumbers(BASE_HP_BY_CLASS, 10); + file.syncNumbers(AGE_RANGES, 10); + file.syncNumbers2D((int *)AGE_RANGES_ADJUST, 2, 10); + file.syncNumbers(STAT_VALUES, 24); + file.syncNumbers(STAT_BONUSES, 24); + file.syncNumbers(ELEMENTAL_CATEGORIES, 6); + file.syncNumbers(ATTRIBUTE_CATEGORIES, 10); + file.syncNumbers(ATTRIBUTE_BONUSES, 72); + file.syncNumbers(ELEMENTAL_RESISTENCES, 37); + file.syncNumbers(ELEMENTAL_DAMAGE, 37); + file.syncNumbers(WEAPON_DAMAGE_BASE, 35); + file.syncNumbers(WEAPON_DAMAGE_MULTIPLIER, 35); + file.syncNumbers(METAL_DAMAGE, 22); + file.syncNumbers(METAL_DAMAGE_PERCENT, 22); + file.syncNumbers(METAL_LAC, 9); + file.syncNumbers(ARMOR_STRENGTHS, 14); + file.syncNumbers(MAKE_ITEM_ARR1, 6); + file.syncNumbers3D((int *)MAKE_ITEM_ARR2, 6, 7, 2); + file.syncNumbers3D((int *)MAKE_ITEM_ARR3, 10, 7, 2); + file.syncNumbers3D((int *)MAKE_ITEM_ARR4, 2, 7, 2); + file.syncNumbers2D((int *)MAKE_ITEM_ARR5, 8, 2); + file.syncNumbers(OUTDOOR_DRAWSTRUCT_INDEXES, 44); + file.syncNumbers2D((int *)TOWN_MAXES, 2, 11); + file.syncStrings2D((String *)TOWN_ACTION_MUSIC, 2, 7); + file.syncStrings(TOWN_ACTION_SHAPES, 7); + file.syncNumbers2D((int *)TOWN_ACTION_FILES, 2, 7); + file.syncString(BANK_TEXT); + file.syncString(BLACKSMITH_TEXT); + file.syncString(GUILD_NOT_MEMBER_TEXT); + file.syncString(GUILD_TEXT); + file.syncString(TAVERN_TEXT); + file.syncString(GOOD_STUFF); + file.syncString(HAVE_A_DRINK); + file.syncString(YOURE_DRUNK); + file.syncNumbers4D((int *)TAVERN_EXIT_LIST, 2, 6, 5, 2); + file.syncString(FOOD_AND_DRINK); + file.syncString(TEMPLE_TEXT); + file.syncString(EXPERIENCE_FOR_LEVEL); + file.syncString(LEARNED_ALL); + file.syncString(ELIGIBLE_FOR_LEVEL); + file.syncString(TRAINING_TEXT); + file.syncString(GOLD_GEMS); + file.syncString(GOLD_GEMS_2); + file.syncString(DEPOSIT_WITHDRAWL[2]); + file.syncString(NOT_ENOUGH_X_IN_THE_Y); + file.syncString(NO_X_IN_THE_Y); + file.syncString(STAT_NAMES[16]); + file.syncString(CONSUMABLE_NAMES[4]); + file.syncString(WHERE_NAMES[2]); + file.syncString(AMOUNT); + file.syncString(FOOD_PACKS_FULL); + file.syncString(BUY_SPELLS); + file.syncString(GUILD_OPTIONS); + file.syncNumbers((int *)MISC_SPELL_INDEX, 74); + file.syncNumbers((int *)SPELL_COSTS, 77); + file.syncNumbers2D((int *)CLOUDS_SPELL_OFFSETS, 5, 20); + file.syncNumbers2D((int *)DARK_SPELL_OFFSETS, 3, 39); + file.syncNumbers2D((int *)DARK_SPELL_RANGES, 12, 2); + file.syncNumbers((int *)SPELL_GEM_COST, 77); + file.syncString(NOT_A_SPELL_CASTER); + file.syncString(SPELLS_FOR); + file.syncString(SPELL_LINES_0_TO_9); + file.syncString(SPELLS_DIALOG_SPELLS); + file.syncString(SPELL_PTS); + file.syncString(GOLD); + file.syncString(SPELLS_PRESS_A_KEY); + file.syncString(SPELLS_PURCHASE); + file.syncString(MAP_TEXT); + file.syncString(LIGHT_COUNT_TEXT); + file.syncString(FIRE_RESISTENCE_TEXT); + file.syncString(ELECRICITY_RESISTENCE_TEXT); + file.syncString(COLD_RESISTENCE_TEXT); + file.syncString(POISON_RESISTENCE_TEXT); + file.syncString(CLAIRVOYANCE_TEXT); + file.syncString(LEVITATE_TEXT); + file.syncString(WALK_ON_WATER_TEXT); + file.syncString(GAME_INFORMATION); + file.syncString(WORLD_GAME_TEXT); + file.syncString(DARKSIDE_GAME_TEXT); + file.syncString(CLOUDS_GAME_TEXT); + file.syncString(SWORDS_GAME_TEXT); + file.syncStrings(WEEK_DAY_STRINGS, 10); + file.syncString(CHARACTER_DETAILS); + file.syncString(PARTY_GOLD); + file.syncString(PLUS_14); + file.syncString(CHARACTER_TEMPLATE); + file.syncString(EXCHANGING_IN_COMBAT); + file.syncString(CURRENT_MAXIMUM_RATING_TEXT); + file.syncString(CURRENT_MAXIMUM_TEXT); + file.syncStrings(RATING_TEXT, 24); + file.syncString(AGE_TEXT); + file.syncString(LEVEL_TEXT); + file.syncString(RESISTENCES_TEXT); + file.syncString(NONE); + file.syncString(EXPERIENCE_TEXT); + file.syncString(ELIGIBLE); + file.syncString(IN_PARTY_IN_BANK); + file.syncString(FOOD_TEXT); + file.syncString(EXCHANGE_WITH_WHOM); + file.syncString(QUICK_REF_LINE); + file.syncString(QUICK_REFERENCE); + file.syncNumbers2D((int *)BLACKSMITH_MAP_IDS, 2, 4); + file.syncString(ITEMS_DIALOG_TEXT1); + file.syncString(ITEMS_DIALOG_TEXT2); + file.syncString(ITEMS_DIALOG_LINE1); + file.syncString(ITEMS_DIALOG_LINE2); + file.syncString(BTN_BUY); + file.syncString(BTN_SELL); + file.syncString(BTN_IDENTIFY); + file.syncString(BTN_FIX); + file.syncString(BTN_USE); + file.syncString(BTN_EQUIP); + file.syncString(BTN_REMOVE); + file.syncString(BTN_DISCARD); + file.syncString(BTN_QUEST); + file.syncString(BTN_ENCHANT); + file.syncString(BTN_RECHARGE); + file.syncString(BTN_GOLD); + file.syncString(ITEM_BROKEN); + file.syncString(ITEM_CURSED); + file.syncStrings(BONUS_NAMES, 7); + file.syncStrings(WEAPON_NAMES, 35); + file.syncStrings(ARMOR_NAMES, 14); + file.syncStrings(ACCESSORY_NAMES, 11); + file.syncStrings(MISC_NAMES, 22); + file.syncStrings(ELEMENTAL_NAMES, 6); + file.syncStrings(ATTRIBUTE_NAMES, 10); + file.syncStrings(EFFECTIVENESS_NAMES, 7); + file.syncStrings(QUEST_ITEM_NAMES, 85); + file.syncNumbers((int *)WEAPON_BASE_COSTS, 35); + file.syncNumbers((int *)ARMOR_BASE_COSTS, 14); + file.syncNumbers((int *)ACCESSORY_BASE_COSTS, 11); + file.syncNumbers((int *)MISC_MATERIAL_COSTS, 22); + file.syncNumbers((int *)MISC_BASE_COSTS, 76); + file.syncNumbers((int *)METAL_BASE_MULTIPLIERS, 22); + file.syncNumbers((int *)ITEM_SKILL_DIVISORS, 4); + file.syncNumbers((int *)RESTRICTION_OFFSETS, 4); + file.syncNumbers((int *)ITEM_RESTRICTIONS, 86); + file.syncString(NOT_PROFICIENT); + file.syncString(NO_ITEMS_AVAILABLE); + file.syncStrings(CATEGORY_NAMES, 4); + file.syncString(X_FOR_THE_Y); + file.syncString(X_FOR_Y); + file.syncString(X_FOR_Y_GOLD); + file.syncString(FMT_CHARGES); + file.syncString(AVAILABLE_GOLD_COST); + file.syncString(CHARGES); + file.syncString(COST); + file.syncStrings(ITEM_ACTIONS, 7); + file.syncString(WHICH_ITEM); + file.syncString(WHATS_YOUR_HURRY); + file.syncString(USE_ITEM_IN_COMBAT); + file.syncString(NO_SPECIAL_ABILITIES); + file.syncString(CANT_CAST_WHILE_ENGAGED); + file.syncString(EQUIPPED_ALL_YOU_CAN); + file.syncString(REMOVE_X_TO_EQUIP_Y); + file.syncString(RING); + file.syncString(MEDAL); + file.syncString(CANNOT_REMOVE_CURSED_ITEM); + file.syncString(CANNOT_DISCARD_CURSED_ITEM); + file.syncString(PERMANENTLY_DISCARD); + file.syncString(BACKPACK_IS_FULL); + file.syncStrings(CATEGORY_BACKPACK_IS_FULL, 4); + file.syncString(BUY_X_FOR_Y_GOLD); + file.syncString(SELL_X_FOR_Y_GOLD); + file.syncString(NO_NEED_OF_THIS); + file.syncString(NOT_RECHARGABLE); + file.syncString(SPELL_FAILED); + file.syncString(NOT_ENCHANTABLE); + file.syncString(ITEM_NOT_BROKEN); + file.syncStrings(FIX_IDENTIFY, 2); + file.syncString(FIX_IDENTIFY_GOLD); + file.syncString(IDENTIFY_ITEM_MSG); + file.syncString(ITEM_DETAILS); + file.syncString(ALL); + file.syncString(FIELD_NONE); + file.syncString(DAMAGE_X_TO_Y); + file.syncString(ELEMENTAL_XY_DAMAGE); + file.syncString(ATTR_XY_BONUS); + file.syncString(EFFECTIVE_AGAINST); + file.syncString(QUESTS_DIALOG_TEXT); + file.syncString(CLOUDS_OF_XEEN_LINE); + file.syncString(DARKSIDE_OF_XEEN_LINE); + file.syncString(NO_QUEST_ITEMS); + file.syncString(NO_CURRENT_QUESTS); + file.syncString(NO_AUTO_NOTES); + file.syncString(QUEST_ITEMS_DATA); + file.syncString(CURRENT_QUESTS_DATA); + file.syncString(AUTO_NOTES_DATA); + file.syncString(REST_COMPLETE); + file.syncString(PARTY_IS_STARVING); + file.syncString(HIT_SPELL_POINTS_RESTORED); + file.syncString(TOO_DANGEROUS_TO_REST); + file.syncString(SOME_CHARS_MAY_DIE); + file.syncString(CANT_DISMISS_LAST_CHAR); + file.syncStrings(REMOVE_DELETE, 2); + file.syncString(REMOVE_OR_DELETE_WHICH); + file.syncString(YOUR_PARTY_IS_FULL); + file.syncString(HAS_SLAYER_SWORD); + file.syncString(SURE_TO_DELETE_CHAR); + file.syncString(CREATE_CHAR_DETAILS); + file.syncString(NEW_CHAR_STATS); + file.syncString(NAME_FOR_NEW_CHARACTER); + file.syncString(SELECT_CLASS_BEFORE_SAVING); + file.syncString(EXCHANGE_ATTR_WITH); + file.syncNumbers((int *)NEW_CHAR_SKILLS, 10); + file.syncNumbers((int *)NEW_CHAR_SKILLS_LEN, 10); + file.syncNumbers((int *)NEW_CHAR_RACE_SKILLS, 10); + file.syncNumbers((int *)RACE_MAGIC_RESISTENCES, 5); + file.syncNumbers((int *)RACE_FIRE_RESISTENCES, 5); + file.syncNumbers((int *)RACE_ELECTRIC_RESISTENCES, 5); + file.syncNumbers((int *)RACE_COLD_RESISTENCES, 5); + file.syncNumbers((int *)RACE_ENERGY_RESISTENCES, 5); + file.syncNumbers((int *)RACE_POISON_RESISTENCES, 5); + file.syncNumbers2D((int *)NEW_CHARACTER_SPELLS, 10, 4); + file.syncString(COMBAT_DETAILS); + file.syncString(NOT_ENOUGH_TO_CAST); + file.syncStrings(SPELL_CAST_COMPONENTS, 2); + file.syncString(CAST_SPELL_DETAILS); + file.syncString(PARTY_FOUND); + file.syncString(BACKPACKS_FULL_PRESS_KEY); + file.syncString(HIT_A_KEY); + file.syncString(GIVE_TREASURE_FORMATTING); + file.syncString(X_FOUND_Y); + file.syncString(ON_WHO); + file.syncString(WHICH_ELEMENT1); + file.syncString(WHICH_ELEMENT2); + file.syncString(DETECT_MONSTERS); + file.syncString(LLOYDS_BEACON); + file.syncString(HOW_MANY_SQUARES); + file.syncString(TOWN_PORTAL); + file.syncNumbers2D((int *)TOWN_MAP_NUMBERS, 2, 5); + file.syncString(MONSTER_DETAILS); + file.syncStrings(MONSTER_SPECIAL_ATTACKS, 23); + file.syncString(IDENTIFY_MONSTERS); + file.syncStrings(EVENT_SAMPLES, 6); + file.syncString(MOONS_NOT_ALIGNED); + file.syncString(AWARDS_FOR); + file.syncString(AWARDS_TEXT); + file.syncString(NO_AWARDS); + file.syncString(WARZONE_BATTLE_MASTER); + file.syncString(WARZONE_MAXED); + file.syncString(WARZONE_LEVEL); + file.syncString(WARZONE_HOW_MANY); + file.syncString(PICKS_THE_LOCK); + file.syncString(UNABLE_TO_PICK_LOCK); + file.syncString(CONTROL_PANEL_TEXT); + file.syncString(CONTROL_PANEL_BUTTONS); + file.syncString(ON); + file.syncString(OFF); + file.syncString(CONFIRM_QUIT); + file.syncString(MR_WIZARD); + file.syncString(NO_LOADING_IN_COMBAT); + file.syncString(NO_SAVING_IN_COMBAT); + file.syncString(QUICK_FIGHT_TEXT); + file.syncStrings(QUICK_FIGHT_OPTIONS, 4); + file.syncStrings(WORLD_END_TEXT, 9); + file.syncString(WORLD_CONGRATULATIONS); + file.syncString(WORLD_CONGRATULATIONS2); + file.syncString(CLOUDS_CONGRATULATIONS1); + file.syncString(CLOUDS_CONGRATULATIONS2); + file.syncStrings(GOOBER, 3); + file.syncStrings(MUSIC_FILES1, 5); + file.syncStrings2D((String *)MUSIC_FILES2, 6, 7); +} } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index c9e0c2ff5a..513e70d1c4 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/files.h" #include "xeen/party.h" #include "xeen/spells.h" @@ -36,344 +37,419 @@ namespace Xeen { class XeenEngine; class Resources { -protected: - Resources(); + /** + * Derived string class to fix automatic type conversion to const char * + */ + class String : public Common::String { + public: + String() : Common::String() {} + String(const Common::String &s) : Common::String(s) {} + operator const char *() { return c_str(); } + }; + + /** + * Derived file class with sync method aliases so that the same + * code from create_xeen can be re-used for both reading and + * writing the resource data + */ + class ResFile : public File { + public: + ResFile() : File("CONSTANTS") {} + + void syncString(String &str) { + str = readString(); + } + void syncStrings(String *str, int count) { + uint tag = readUint32LE(); + assert(tag == MKTAG(count, 0, 0, 0)); + for (int idx = 0; idx < count; ++idx) + str[idx] = readString(); + } + void syncStrings2D(String *str, int count1, int count2) { + uint tag = readUint32LE(); + assert(tag == MKTAG(count1, count2, 0, 0)); + for (int idx = 0; idx < count1 * count2; ++idx) + str[idx] = readString(); + } + void syncNumber(int &val) { + val = readSint32LE(); + } + void syncNumbers(int *vals, int count) { + uint tag = readUint32LE(); + assert(tag == MKTAG(count, 0, 0, 0)); + for (int idx = 0; idx < count; ++idx) + vals[idx] = readSint32LE(); + } + void syncNumbers2D(int *vals, int count1, int count2) { + uint tag = readUint32LE(); + assert(tag == MKTAG(count1, count2, 0, 0)); + for (int idx = 0; idx < count1 * count2; ++idx) + vals[idx] = readSint32LE(); + } + void syncNumbers3D(int *vals, int count1, int count2, int count3) { + uint tag = readUint32LE(); + assert(tag == MKTAG(count1, count2, count3, 0)); + for (int idx = 0; idx < count1 * count2 * count3; ++idx) + vals[idx] = readSint32LE(); + } + void syncNumbers4D(int *vals, int count1, int count2, int count3, int count4) { + uint tag = readUint32LE(); + assert(tag == MKTAG(count1, count2, count3, count4)); + for (int idx = 0; idx < count1 * count2 * count3 * count4; ++idx) + vals[idx] = readSint32LE(); + } + void syncBytes2D(byte *vals, int count1, int count2) { + uint tag = readUint32LE(); + assert(tag == MKTAG(count1, count2, 0, 0)); + read(vals, count1 * count2); + } + }; +private: + /** + * Loads all the constants data stored in the xeen.css + */ + void loadData(); public: SpriteResource _globalSprites; Common::StringArray _maeNames; // Magic and equipment names - static const char *const CREDITS; - static const char *const OPTIONS_TITLE; - static const char *const THE_PARTY_NEEDS_REST; - static const char *const WHO_WILL; - static const char *const HOW_MUCH; - static const char *const WHATS_THE_PASSWORD; - static const char *const IN_NO_CONDITION; - static const char *const NOTHING_HERE; - static const char *const TERRAIN_TYPES[6]; - static const char *const OUTDOORS_WALL_TYPES[16]; - static const char *const SURFACE_NAMES[16]; - static const char *const WHO_ACTIONS[32]; - static const char *const WHO_WILL_ACTIONS[4]; - static const byte SYMBOLS[20][64]; - static const byte TEXT_COLORS[40][4]; - static const char *const DIRECTION_TEXT_UPPER[4]; - static const char *const DIRECTION_TEXT[4]; - static const char *const RACE_NAMES[5]; - static const int RACE_HP_BONUSES[5]; - static const int RACE_SP_BONUSES[5][2]; - static const char *const CLASS_NAMES[11]; - static const uint CLASS_EXP_LEVELS[10]; - static const char *const ALIGNMENT_NAMES[3]; - static const char *const SEX_NAMES[2]; - static const char *const SKILL_NAMES[18]; - static const char *const CONDITION_NAMES[17]; - static const int CONDITION_COLORS[17]; - static const char *const GOOD; - static const char *const BLESSED; - static const char *const POWER_SHIELD; - static const char *const HOLY_BONUS; - static const char *const HEROISM; - static const char *const IN_PARTY; - static const char *const PARTY_DETAILS; - static const char *const PARTY_DIALOG_TEXT; - static const int FACE_CONDITION_FRAMES[17]; - static const int CHAR_FACES_X[6]; - static const int HP_BARS_X[6]; - static const char *const NO_ONE_TO_ADVENTURE_WITH; - static const byte DARKNESS_XLAT[3][256]; - static const char *const YOUR_ROSTER_IS_FULL; - static const char *const PLEASE_WAIT; - static const char *const OOPS; - static const int8 SCREEN_POSITIONING_X[4][48]; - static const int8 SCREEN_POSITIONING_Y[4][48]; - static const int MONSTER_GRID_BITMASK[12]; - static const int INDOOR_OBJECT_X[2][12]; - static const int MAP_OBJECT_Y[2][12]; - static const int INDOOR_MONSTERS_Y[4]; - static const int OUTDOOR_OBJECT_X[2][12]; - static const int OUTDOOR_MONSTER_INDEXES[26]; - static const int OUTDOOR_MONSTERS_Y[26]; - static const int DIRECTION_ANIM_POSITIONS[4][4]; - static const byte WALL_SHIFTS[4][48]; - static const int DRAW_NUMBERS[25]; - static const int DRAW_FRAMES[25][2]; - static const int COMBAT_FLOAT_X[8]; - static const int COMBAT_FLOAT_Y[8]; - static const int MONSTER_EFFECT_FLAGS[15][8]; - static const uint SPELLS_ALLOWED[3][40]; - static const int BASE_HP_BY_CLASS[10]; - static const int AGE_RANGES[10]; - static const int AGE_RANGES_ADJUST[2][10]; - static const uint STAT_VALUES[24]; - static const int STAT_BONUSES[24]; - static const int ELEMENTAL_CATEGORIES[6]; - static const int ATTRIBUTE_CATEGORIES[10]; - static const int ATTRIBUTE_BONUSES[72]; - static const int ELEMENTAL_RESISTENCES[37]; - static const int ELEMENTAL_DAMAGE[37]; - static const int WEAPON_DAMAGE_BASE[35]; - static const int WEAPON_DAMAGE_MULTIPLIER[35]; - static const int METAL_DAMAGE[22]; - static const int METAL_DAMAGE_PERCENT[22]; - static const int METAL_LAC[9]; - static const int ARMOR_STRENGTHS[14]; - static const int MAKE_ITEM_ARR1[6]; - static const int MAKE_ITEM_ARR2[6][7][2]; - static const int MAKE_ITEM_ARR3[10][7][2]; - static const int MAKE_ITEM_ARR4[2][7][2]; - static const int MAKE_ITEM_ARR5[8][2]; - static const int OUTDOOR_DRAWSTRUCT_INDEXES[44]; - static const int TOWN_MAXES[2][11]; - static const char *const TOWN_ACTION_MUSIC[2][7]; - static const char *const TOWN_ACTION_SHAPES[7]; - static const int TOWN_ACTION_FILES[2][7]; - static const char *const BANK_TEXT; - static const char *const BLACKSMITH_TEXT; - static const char *const GUILD_NOT_MEMBER_TEXT; - static const char *const GUILD_TEXT; - static const char *const TAVERN_TEXT; - static const char *const GOOD_STUFF; - static const char *const HAVE_A_DRINK; - static const char *const YOURE_DRUNK; - static const int TAVERN_EXIT_LIST[2][6][5][2]; - static const char *const FOOD_AND_DRINK; - static const char *const TEMPLE_TEXT; - static const char *const EXPERIENCE_FOR_LEVEL; - static const char *const LEARNED_ALL; - static const char *const ELIGIBLE_FOR_LEVEL; - static const char *const TRAINING_TEXT; - static const char *const GOLD_GEMS; - static const char *const GOLD_GEMS_2; - static const char *const DEPOSIT_WITHDRAWL[2]; - static const char *const NOT_ENOUGH_X_IN_THE_Y; - static const char *const NO_X_IN_THE_Y; - static const char *const STAT_NAMES[16]; - static const char *const CONSUMABLE_NAMES[4]; - static const char *const WHERE_NAMES[2]; - static const char *const AMOUNT; - static const char *const FOOD_PACKS_FULL; - static const char *const BUY_SPELLS; - static const char *const GUILD_OPTIONS; - static const int MISC_SPELL_INDEX[74]; - static const int SPELL_COSTS[77]; - static const int CLOUDS_SPELL_OFFSETS[5][20]; - static const uint DARK_SPELL_OFFSETS[3][39]; - static const int DARK_SPELL_RANGES[12][2]; - static const int SPELL_LEVEL_OFFSETS[3][39]; - static const int SPELL_GEM_COST[77]; - static const char *const NOT_A_SPELL_CASTER; - static const char *const SPELLS_FOR; - static const char *const SPELL_LINES_0_TO_9; - static const char *const SPELLS_DIALOG_SPELLS; - static const char *const SPELL_PTS; - static const char *const GOLD; - static const char *const SPELLS_PRESS_A_KEY; - static const char *const SPELLS_PURCHASE; - static const char *const MAP_TEXT; - static const char *const LIGHT_COUNT_TEXT; - static const char *const FIRE_RESISTENCE_TEXT; - static const char *const ELECRICITY_RESISTENCE_TEXT; - static const char *const COLD_RESISTENCE_TEXT; - static const char *const POISON_RESISTENCE_TEXT; - static const char *const CLAIRVOYANCE_TEXT; - static const char *const LEVITATE_TEXT; - static const char *const WALK_ON_WATER_TEXT; - static const char *const GAME_INFORMATION; - static const char *const WORLD_GAME_TEXT; - static const char *const DARKSIDE_GAME_TEXT; - static const char *const CLOUDS_GAME_TEXT; - static const char *const SWORDS_GAME_TEXT; - static const char *const WEEK_DAY_STRINGS[10]; - static const char *const CHARACTER_DETAILS; - static const char *const PARTY_GOLD; - static const char *const PLUS_14; - static const char *const CHARACTER_TEMPLATE; - static const char *const EXCHANGING_IN_COMBAT; - static const char *const CURRENT_MAXIMUM_RATING_TEXT; - static const char *const CURRENT_MAXIMUM_TEXT; - static const char *const RATING_TEXT[24]; - static const char *const AGE_TEXT; - static const char *const LEVEL_TEXT; - static const char *const RESISTENCES_TEXT; - static const char *const NONE; - static const char *const EXPERIENCE_TEXT; - static const char *const ELIGIBLE; - static const char *const IN_PARTY_IN_BANK; - static const char *const FOOD_TEXT; - static const char *const EXCHANGE_WITH_WHOM; - static const char *const QUICK_REF_LINE; - static const char *const QUICK_REFERENCE; - static const uint BLACKSMITH_MAP_IDS[2][4]; - static const char *const ITEMS_DIALOG_TEXT1; - static const char *const ITEMS_DIALOG_TEXT2; - static const char *const ITEMS_DIALOG_LINE1; - static const char *const ITEMS_DIALOG_LINE2; - static const char *const BTN_BUY; - static const char *const BTN_SELL; - static const char *const BTN_IDENTIFY; - static const char *const BTN_FIX; - static const char *const BTN_USE; - static const char *const BTN_EQUIP; - static const char *const BTN_REMOVE; - static const char *const BTN_DISCARD; - static const char *const BTN_QUEST; - static const char *const BTN_ENCHANT; - static const char *const BTN_RECHARGE; - static const char *const BTN_GOLD; - static const char *const ITEM_BROKEN; - static const char *const ITEM_CURSED; - static const char *const BONUS_NAMES[7]; - static const char *const WEAPON_NAMES[35]; - static const char *const ARMOR_NAMES[14]; - static const char *const ACCESSORY_NAMES[11]; - static const char *const MISC_NAMES[22]; - static const char *const *ITEM_NAMES[4]; - static const char *const ELEMENTAL_NAMES[6]; - static const char *const ATTRIBUTE_NAMES[10]; - static const char *const EFFECTIVENESS_NAMES[7]; - static const char *const QUEST_ITEM_NAMES[85]; - static const int WEAPON_BASE_COSTS[35]; - static const int ARMOR_BASE_COSTS[14]; - static const int ACCESSORY_BASE_COSTS[11]; - static const int MISC_MATERIAL_COSTS[22]; - static const int MISC_BASE_COSTS[76]; - static const int METAL_BASE_MULTIPLIERS[22]; - static const int ITEM_SKILL_DIVISORS[4]; - static const int RESTRICTION_OFFSETS[4]; - static const int ITEM_RESTRICTIONS[86]; - static const char *const NOT_PROFICIENT; - static const char *const NO_ITEMS_AVAILABLE; - static const char *const CATEGORY_NAMES[4]; - static const char *const X_FOR_THE_Y; - static const char *const X_FOR_Y; - static const char *const X_FOR_Y_GOLD; - static const char *const FMT_CHARGES; - static const char *const AVAILABLE_GOLD_COST; - static const char *const CHARGES; - static const char *const COST; - static const char *const ITEM_ACTIONS[7]; - static const char *const WHICH_ITEM; - static const char *const WHATS_YOUR_HURRY; + String *ITEM_NAMES[4]; - static const char *const USE_ITEM_IN_COMBAT; - - static const char *const NO_SPECIAL_ABILITIES; - - static const char *const CANT_CAST_WHILE_ENGAGED; - - static const char *const EQUIPPED_ALL_YOU_CAN; - static const char *const REMOVE_X_TO_EQUIP_Y; - static const char *const RING; - static const char *const MEDAL; - static const char *const CANNOT_REMOVE_CURSED_ITEM; - static const char *const CANNOT_DISCARD_CURSED_ITEM; - static const char *const PERMANENTLY_DISCARD; - static const char *const BACKPACK_IS_FULL; - static const char *const CATEGORY_BACKPACK_IS_FULL[4]; - static const char *const BUY_X_FOR_Y_GOLD; - static const char *const SELL_X_FOR_Y_GOLD; - static const char *const NO_NEED_OF_THIS; - static const char *const NOT_RECHARGABLE; - static const char *const SPELL_FAILED; - static const char *const NOT_ENCHANTABLE; - static const char *const ITEM_NOT_BROKEN; - static const char *const FIX_IDENTIFY[2]; - static const char *const FIX_IDENTIFY_GOLD; - static const char *const IDENTIFY_ITEM_MSG; - static const char *const ITEM_DETAILS; - static const char *const ALL; - static const char *const FIELD_NONE; - static const char *const DAMAGE_X_TO_Y; - static const char *const ELEMENTAL_XY_DAMAGE; - static const char *const ATTR_XY_BONUS; - static const char *const EFFECTIVE_AGAINST; - static const char *const QUESTS_DIALOG_TEXT; - static const char *const CLOUDS_OF_XEEN_LINE; - static const char *const DARKSIDE_OF_XEEN_LINE; - static const char *const NO_QUEST_ITEMS; - static const char *const NO_CURRENT_QUESTS; - static const char *const NO_AUTO_NOTES; - static const char *const QUEST_ITEMS_DATA; - static const char *const CURRENT_QUESTS_DATA; - static const char *const AUTO_NOTES_DATA; - static const char *const REST_COMPLETE; - static const char *const PARTY_IS_STARVING; - static const char *const HIT_SPELL_POINTS_RESTORED; - static const char *const TOO_DANGEROUS_TO_REST; - static const char *const SOME_CHARS_MAY_DIE; - static const char *const CANT_DISMISS_LAST_CHAR; - static const char *const REMOVE_DELETE[2]; - static const char *const REMOVE_OR_DELETE_WHICH; - static const char *const YOUR_PARTY_IS_FULL; - static const char *const HAS_SLAYER_SWORD; - static const char *const SURE_TO_DELETE_CHAR; - static const char *const CREATE_CHAR_DETAILS; - static const char *const NEW_CHAR_STATS; - static const char *const NAME_FOR_NEW_CHARACTER; - static const char *const SELECT_CLASS_BEFORE_SAVING; - static const char *const EXCHANGE_ATTR_WITH; - static const int NEW_CHAR_SKILLS[10]; - static const int NEW_CHAR_SKILLS_LEN[10]; - static const int NEW_CHAR_RACE_SKILLS[10]; - static const int RACE_MAGIC_RESISTENCES[5]; - static const int RACE_FIRE_RESISTENCES[5]; - static const int RACE_ELECTRIC_RESISTENCES[5]; - static const int RACE_COLD_RESISTENCES[5]; - static const int RACE_ENERGY_RESISTENCES[5]; - static const int RACE_POISON_RESISTENCES[5]; - static const int NEW_CHARACTER_SPELLS[10][4]; - static const char *const COMBAT_DETAILS; - static const char *NOT_ENOUGH_TO_CAST; - static const char *SPELL_CAST_COMPONENTS[2]; - static const char *const CAST_SPELL_DETAILS; - static const char *const PARTY_FOUND; - static const char *const BACKPACKS_FULL_PRESS_KEY; - static const char *const HIT_A_KEY; - static const char *const GIVE_TREASURE_FORMATTING; - static const char *const X_FOUND_Y; - static const char *const ON_WHO; - static const char *const WHICH_ELEMENT1; - static const char *const WHICH_ELEMENT2; - static const char *const DETECT_MONSTERS; - static const char *const LLOYDS_BEACON; - static const char *const HOW_MANY_SQUARES; - static const char *const TOWN_PORTAL; - static const int TOWN_MAP_NUMBERS[2][5]; - static const char *const MONSTER_DETAILS; - static const char *const MONSTER_SPECIAL_ATTACKS[23]; - static const char *const IDENTIFY_MONSTERS; - static const char *const EVENT_SAMPLES[6]; - static const char *const MOONS_NOT_ALIGNED; - static const char *const AWARDS_FOR; - static const char *const AWARDS_TEXT; - static const char *const NO_AWARDS; - static const char *const WARZONE_BATTLE_MASTER; - static const char *const WARZONE_MAXED; - static const char *const WARZONE_LEVEL; - static const char *const WARZONE_HOW_MANY; - static const char *const PICKS_THE_LOCK; - static const char *const UNABLE_TO_PICK_LOCK; - static const char *const CONTROL_PANEL_TEXT; - static const char *const CONTROL_PANEL_BUTTONS; - static const char *const ON; - static const char *const OFF; - static const char *const CONFIRM_QUIT; - static const char *const MR_WIZARD; - static const char *const NO_LOADING_IN_COMBAT; - static const char *const NO_SAVING_IN_COMBAT; - static const char *const QUICK_FIGHT_TEXT; - static const char *const QUICK_FIGHT_OPTIONS[4]; - static const char *const WORLD_END_TEXT[9]; - static const char *const WORLD_CONGRATULATIONS; - static const char *const WORLD_CONGRATULATIONS2; - static const char *const CLOUDS_CONGRATULATIONS1; - static const char *const CLOUDS_CONGRATULATIONS2; - static const char *const GOOBER[3]; + // Data loaded from xeen.ccs + String CREDITS; + String OPTIONS_TITLE; + String THE_PARTY_NEEDS_REST; + String WHO_WILL; + String HOW_MUCH; + String WHATS_THE_PASSWORD; + String IN_NO_CONDITION; + String NOTHING_HERE; + String TERRAIN_TYPES[6]; + String OUTDOORS_WALL_TYPES[16]; + String SURFACE_NAMES[16]; + String WHO_ACTIONS[32]; + String WHO_WILL_ACTIONS[4]; + byte SYMBOLS[20][64]; + byte TEXT_COLORS[40][4]; + String DIRECTION_TEXT_UPPER[4]; + String DIRECTION_TEXT[4]; + String RACE_NAMES[5]; + int RACE_HP_BONUSES[5]; + int RACE_SP_BONUSES[5][2]; + String CLASS_NAMES[11]; + int CLASS_EXP_LEVELS[10]; + String ALIGNMENT_NAMES[3]; + String SEX_NAMES[2]; + String SKILL_NAMES[18]; + String CONDITION_NAMES[17]; + int CONDITION_COLORS[17]; + String GOOD; + String BLESSED; + String POWER_SHIELD; + String HOLY_BONUS; + String HEROISM; + String IN_PARTY; + String PARTY_DETAILS; + String PARTY_DIALOG_TEXT; + int FACE_CONDITION_FRAMES[17]; + int CHAR_FACES_X[6]; + int HP_BARS_X[6]; + String NO_ONE_TO_ADVENTURE_WITH; + byte DARKNESS_XLAT[3][256]; + String YOUR_ROSTER_IS_FULL; + String PLEASE_WAIT; + String OOPS; + int SCREEN_POSITIONING_X[4][48]; + int SCREEN_POSITIONING_Y[4][48]; + int MONSTER_GRID_BITMASK[12]; + int INDOOR_OBJECT_X[2][12]; + int MAP_OBJECT_Y[2][12]; + int INDOOR_MONSTERS_Y[4]; + int OUTDOOR_OBJECT_X[2][12]; + int OUTDOOR_MONSTER_INDEXES[26]; + int OUTDOOR_MONSTERS_Y[26]; + int DIRECTION_ANIM_POSITIONS[4][4]; + byte WALL_SHIFTS[4][48]; + int DRAW_NUMBERS[25]; + int DRAW_FRAMES[25][2]; + int COMBAT_FLOAT_X[8]; + int COMBAT_FLOAT_Y[8]; + int MONSTER_EFFECT_FLAGS[15][8]; + int SPELLS_ALLOWED[3][40]; + int BASE_HP_BY_CLASS[10]; + int AGE_RANGES[10]; + int AGE_RANGES_ADJUST[2][10]; + int STAT_VALUES[24]; + int STAT_BONUSES[24]; + int ELEMENTAL_CATEGORIES[6]; + int ATTRIBUTE_CATEGORIES[10]; + int ATTRIBUTE_BONUSES[72]; + int ELEMENTAL_RESISTENCES[37]; + int ELEMENTAL_DAMAGE[37]; + int WEAPON_DAMAGE_BASE[35]; + int WEAPON_DAMAGE_MULTIPLIER[35]; + int METAL_DAMAGE[22]; + int METAL_DAMAGE_PERCENT[22]; + int METAL_LAC[9]; + int ARMOR_STRENGTHS[14]; + int MAKE_ITEM_ARR1[6]; + int MAKE_ITEM_ARR2[6][7][2]; + int MAKE_ITEM_ARR3[10][7][2]; + int MAKE_ITEM_ARR4[2][7][2]; + int MAKE_ITEM_ARR5[8][2]; + int OUTDOOR_DRAWSTRUCT_INDEXES[44]; + int TOWN_MAXES[2][11]; + String TOWN_ACTION_MUSIC[2][7]; + String TOWN_ACTION_SHAPES[7]; + int TOWN_ACTION_FILES[2][7]; + String BANK_TEXT; + String BLACKSMITH_TEXT; + String GUILD_NOT_MEMBER_TEXT; + String GUILD_TEXT; + String TAVERN_TEXT; + String GOOD_STUFF; + String HAVE_A_DRINK; + String YOURE_DRUNK; + int TAVERN_EXIT_LIST[2][6][5][2]; + String FOOD_AND_DRINK; + String TEMPLE_TEXT; + String EXPERIENCE_FOR_LEVEL; + String LEARNED_ALL; + String ELIGIBLE_FOR_LEVEL; + String TRAINING_TEXT; + String GOLD_GEMS; + String GOLD_GEMS_2; + String DEPOSIT_WITHDRAWL[2]; + String NOT_ENOUGH_X_IN_THE_Y; + String NO_X_IN_THE_Y; + String STAT_NAMES[16]; + String CONSUMABLE_NAMES[4]; + String WHERE_NAMES[2]; + String AMOUNT; + String FOOD_PACKS_FULL; + String BUY_SPELLS; + String GUILD_OPTIONS; + int MISC_SPELL_INDEX[74]; + int SPELL_COSTS[77]; + int CLOUDS_SPELL_OFFSETS[5][20]; + int DARK_SPELL_OFFSETS[3][39]; + int DARK_SPELL_RANGES[12][2]; + int SPELL_LEVEL_OFFSETS[3][39]; + int SPELL_GEM_COST[77]; + String NOT_A_SPELL_CASTER; + String SPELLS_FOR; + String SPELL_LINES_0_TO_9; + String SPELLS_DIALOG_SPELLS; + String SPELL_PTS; + String GOLD; + String SPELLS_PRESS_A_KEY; + String SPELLS_PURCHASE; + String MAP_TEXT; + String LIGHT_COUNT_TEXT; + String FIRE_RESISTENCE_TEXT; + String ELECRICITY_RESISTENCE_TEXT; + String COLD_RESISTENCE_TEXT; + String POISON_RESISTENCE_TEXT; + String CLAIRVOYANCE_TEXT; + String LEVITATE_TEXT; + String WALK_ON_WATER_TEXT; + String GAME_INFORMATION; + String WORLD_GAME_TEXT; + String DARKSIDE_GAME_TEXT; + String CLOUDS_GAME_TEXT; + String SWORDS_GAME_TEXT; + String WEEK_DAY_STRINGS[10]; + String CHARACTER_DETAILS; + String PARTY_GOLD; + String PLUS_14; + String CHARACTER_TEMPLATE; + String EXCHANGING_IN_COMBAT; + String CURRENT_MAXIMUM_RATING_TEXT; + String CURRENT_MAXIMUM_TEXT; + String RATING_TEXT[24]; + String AGE_TEXT; + String LEVEL_TEXT; + String RESISTENCES_TEXT; + String NONE; + String EXPERIENCE_TEXT; + String ELIGIBLE; + String IN_PARTY_IN_BANK; + String FOOD_TEXT; + String EXCHANGE_WITH_WHOM; + String QUICK_REF_LINE; + String QUICK_REFERENCE; + int BLACKSMITH_MAP_IDS[2][4]; + String ITEMS_DIALOG_TEXT1; + String ITEMS_DIALOG_TEXT2; + String ITEMS_DIALOG_LINE1; + String ITEMS_DIALOG_LINE2; + String BTN_BUY; + String BTN_SELL; + String BTN_IDENTIFY; + String BTN_FIX; + String BTN_USE; + String BTN_EQUIP; + String BTN_REMOVE; + String BTN_DISCARD; + String BTN_QUEST; + String BTN_ENCHANT; + String BTN_RECHARGE; + String BTN_GOLD; + String ITEM_BROKEN; + String ITEM_CURSED; + String BONUS_NAMES[7]; + String WEAPON_NAMES[35]; + String ARMOR_NAMES[14]; + String ACCESSORY_NAMES[11]; + String MISC_NAMES[22]; + String ELEMENTAL_NAMES[6]; + String ATTRIBUTE_NAMES[10]; + String EFFECTIVENESS_NAMES[7]; + String QUEST_ITEM_NAMES[85]; + int WEAPON_BASE_COSTS[35]; + int ARMOR_BASE_COSTS[14]; + int ACCESSORY_BASE_COSTS[11]; + int MISC_MATERIAL_COSTS[22]; + int MISC_BASE_COSTS[76]; + int METAL_BASE_MULTIPLIERS[22]; + int ITEM_SKILL_DIVISORS[4]; + int RESTRICTION_OFFSETS[4]; + int ITEM_RESTRICTIONS[86]; + String NOT_PROFICIENT; + String NO_ITEMS_AVAILABLE; + String CATEGORY_NAMES[4]; + String X_FOR_THE_Y; + String X_FOR_Y; + String X_FOR_Y_GOLD; + String FMT_CHARGES; + String AVAILABLE_GOLD_COST; + String CHARGES; + String COST; + String ITEM_ACTIONS[7]; + String WHICH_ITEM; + String WHATS_YOUR_HURRY; + String USE_ITEM_IN_COMBAT; + String NO_SPECIAL_ABILITIES; + String CANT_CAST_WHILE_ENGAGED; + String EQUIPPED_ALL_YOU_CAN; + String REMOVE_X_TO_EQUIP_Y; + String RING; + String MEDAL; + String CANNOT_REMOVE_CURSED_ITEM; + String CANNOT_DISCARD_CURSED_ITEM; + String PERMANENTLY_DISCARD; + String BACKPACK_IS_FULL; + String CATEGORY_BACKPACK_IS_FULL[4]; + String BUY_X_FOR_Y_GOLD; + String SELL_X_FOR_Y_GOLD; + String NO_NEED_OF_THIS; + String NOT_RECHARGABLE; + String SPELL_FAILED; + String NOT_ENCHANTABLE; + String ITEM_NOT_BROKEN; + String FIX_IDENTIFY[2]; + String FIX_IDENTIFY_GOLD; + String IDENTIFY_ITEM_MSG; + String ITEM_DETAILS; + String ALL; + String FIELD_NONE; + String DAMAGE_X_TO_Y; + String ELEMENTAL_XY_DAMAGE; + String ATTR_XY_BONUS; + String EFFECTIVE_AGAINST; + String QUESTS_DIALOG_TEXT; + String CLOUDS_OF_XEEN_LINE; + String DARKSIDE_OF_XEEN_LINE; + String NO_QUEST_ITEMS; + String NO_CURRENT_QUESTS; + String NO_AUTO_NOTES; + String QUEST_ITEMS_DATA; + String CURRENT_QUESTS_DATA; + String AUTO_NOTES_DATA; + String REST_COMPLETE; + String PARTY_IS_STARVING; + String HIT_SPELL_POINTS_RESTORED; + String TOO_DANGEROUS_TO_REST; + String SOME_CHARS_MAY_DIE; + String CANT_DISMISS_LAST_CHAR; + String REMOVE_DELETE[2]; + String REMOVE_OR_DELETE_WHICH; + String YOUR_PARTY_IS_FULL; + String HAS_SLAYER_SWORD; + String SURE_TO_DELETE_CHAR; + String CREATE_CHAR_DETAILS; + String NEW_CHAR_STATS; + String NAME_FOR_NEW_CHARACTER; + String SELECT_CLASS_BEFORE_SAVING; + String EXCHANGE_ATTR_WITH; + int NEW_CHAR_SKILLS[10]; + int NEW_CHAR_SKILLS_LEN[10]; + int NEW_CHAR_RACE_SKILLS[10]; + int RACE_MAGIC_RESISTENCES[5]; + int RACE_FIRE_RESISTENCES[5]; + int RACE_ELECTRIC_RESISTENCES[5]; + int RACE_COLD_RESISTENCES[5]; + int RACE_ENERGY_RESISTENCES[5]; + int RACE_POISON_RESISTENCES[5]; + int NEW_CHARACTER_SPELLS[10][4]; + String COMBAT_DETAILS; + String NOT_ENOUGH_TO_CAST; + String SPELL_CAST_COMPONENTS[2]; + String CAST_SPELL_DETAILS; + String PARTY_FOUND; + String BACKPACKS_FULL_PRESS_KEY; + String HIT_A_KEY; + String GIVE_TREASURE_FORMATTING; + String X_FOUND_Y; + String ON_WHO; + String WHICH_ELEMENT1; + String WHICH_ELEMENT2; + String DETECT_MONSTERS; + String LLOYDS_BEACON; + String HOW_MANY_SQUARES; + String TOWN_PORTAL; + int TOWN_MAP_NUMBERS[2][5]; + String MONSTER_DETAILS; + String MONSTER_SPECIAL_ATTACKS[23]; + String IDENTIFY_MONSTERS; + String EVENT_SAMPLES[6]; + String MOONS_NOT_ALIGNED; + String AWARDS_FOR; + String AWARDS_TEXT; + String NO_AWARDS; + String WARZONE_BATTLE_MASTER; + String WARZONE_MAXED; + String WARZONE_LEVEL; + String WARZONE_HOW_MANY; + String PICKS_THE_LOCK; + String UNABLE_TO_PICK_LOCK; + String CONTROL_PANEL_TEXT; + String CONTROL_PANEL_BUTTONS; + String ON; + String OFF; + String CONFIRM_QUIT; + String MR_WIZARD; + String NO_LOADING_IN_COMBAT; + String NO_SAVING_IN_COMBAT; + String QUICK_FIGHT_TEXT; + String QUICK_FIGHT_OPTIONS[4]; + String WORLD_END_TEXT[9]; + String WORLD_CONGRATULATIONS; + String WORLD_CONGRATULATIONS2; + String CLOUDS_CONGRATULATIONS1; + String CLOUDS_CONGRATULATIONS2; + String GOOBER[3]; + String MUSIC_FILES1[5]; + String MUSIC_FILES2[6][7]; public: /** + * Constructor + */ + Resources(); + + /** * Initializes an instnace of the resources */ - static Resources *init(XeenEngine *vm); + Resources *init(XeenEngine *vm); }; extern Resources *g_resources; diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 51c22dd6db..27d33824fc 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -1560,7 +1560,7 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) { // Check if the character class can cast the particular spell for (int idx = 0; idx < 39; ++idx) { - if (Res.SPELLS_ALLOWED[category][idx] == val) { + if (Res.SPELLS_ALLOWED[category][idx] == (int)val) { // Can cast it. Check if the player has it in their spellbook if (ps._spells[idx]) v = val; diff --git a/engines/xeen/worldofxeen/darkside_cutscenes.cpp b/engines/xeen/worldofxeen/darkside_cutscenes.cpp index a772500eaa..b02e7d9608 100644 --- a/engines/xeen/worldofxeen/darkside_cutscenes.cpp +++ b/engines/xeen/worldofxeen/darkside_cutscenes.cpp @@ -1203,7 +1203,7 @@ void DarkSideCutscenes::showDarkSideScore(uint endingScore) { saves.saveGame(); } -void DarkSideCutscenes::showPharaohEndText(const char *msg1, const char *msg2, const char *msg3) { +void DarkSideCutscenes::showPharaohEndText(const Common::String &msg1, const Common::String &msg2, const Common::String &msg3) { const int YLIST[32] = { -3, -3, -3, -3, -3, -3, -3, -3, -1, 0, 0, 0, 0, 0, 0, 0, -1, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3 @@ -1225,8 +1225,12 @@ void DarkSideCutscenes::showPharaohEndText(const char *msg1, const char *msg2, c Windows &windows = *_vm->_windows; SpriteResource claw("claw.int"); SpriteResource dragon1("dragon1.int"); - int numPages = 0 + (msg1 ? 1 : 0) + (msg2 ? 1 : 0) + (msg3 ? 1 : 0); - const char *const text[3] = { msg1, msg2, msg3 }; + int numPages = 0 + (msg1.empty() ? 0 : 1) + (msg2.empty() ? 0 : 1) + (msg3.empty() ? 0 : 1); + const char *const text[3] = { + msg1.empty() ? nullptr : msg1.c_str(), + msg2.empty() ? nullptr : msg2.c_str(), + msg3.empty() ? nullptr : msg3.c_str() + }; screen.loadBackground("3room.raw"); screen.saveBackground(); diff --git a/engines/xeen/worldofxeen/darkside_cutscenes.h b/engines/xeen/worldofxeen/darkside_cutscenes.h index f2dd5c5045..9c8db4d8ae 100644 --- a/engines/xeen/worldofxeen/darkside_cutscenes.h +++ b/engines/xeen/worldofxeen/darkside_cutscenes.h @@ -61,7 +61,13 @@ protected: /** * Shows the Pharaoh ending screen where score text is shown */ - void showPharaohEndText(const char *msg1, const char *msg2 = nullptr, const char *msg3 = nullptr); + void showPharaohEndText(const Common::String &msg1, const Common::String &msg2, const Common::String &msg3); + void showPharaohEndText(const Common::String &msg1) { + showPharaohEndText(msg1, "", ""); + } + void showPharaohEndText(const Common::String &msg1, const Common::String &msg2) { + showPharaohEndText(msg1, msg2, ""); + } public: DarkSideCutscenes(XeenEngine *vm) : Cutscenes(vm) {} diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 0730760d14..8e22965e2f 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -86,10 +86,13 @@ XeenEngine::~XeenEngine() { g_vm = nullptr; } -void XeenEngine::initialize() { +bool XeenEngine::initialize() { // Create sub-objects of the engine _files = new FileManager(this); - _resources = Resources::init(this); + if (!_files->setup()) + return false; + + _resources = new Resources(); _combat = new Combat(this); _debugger = new Debugger(this); _events = new EventsManager(this); @@ -119,12 +122,13 @@ void XeenEngine::initialize() { if (saveSlot >= 0 && saveSlot <= 999) _loadSaveSlot = saveSlot; } + + return true; } Common::Error XeenEngine::run() { - initialize(); - - outerGameLoop(); + if (initialize()) + outerGameLoop(); return Common::kNoError; } @@ -256,4 +260,16 @@ void XeenEngine::syncSoundSettings() { _sound->updateSoundSettings(); } +void XeenEngine::GUIError(const char *msg, ...) { + char buffer[STRINGBUFLEN]; + va_list va; + + // Generate the full error message + va_start(va, msg); + vsnprintf(buffer, STRINGBUFLEN, msg, va); + va_end(va); + + GUIErrorMessage(buffer); +} + } // End of namespace Xeen diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index cbf9ff3ed4..652284b26f 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -108,7 +108,10 @@ private: const XeenGameDescription *_gameDescription; Common::RandomSource _randomSource; private: - void initialize(); + /** + * Initializes all the engine sub-objects + */ + bool initialize(); // Engine APIs virtual Common::Error run(); @@ -176,6 +179,11 @@ public: int getRandomNumber(int minNumber, int maxNumber); /** + * Displays an error message in a GUI dialog + */ + void GUIError(const char *msg, ...) GCC_PRINTF(2, 3); + + /** * Returns true if the game should be exited (and likely return to game menu) */ bool shouldExit() const { return _quitMode != QMODE_NONE || shouldQuit(); } |