681 lines
18 KiB
C++
681 lines
18 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "common/config-manager.h"
|
|
#include "common/file.h"
|
|
|
|
#include "ultima/ultima8/misc/common_types.h"
|
|
#include "ultima/ultima8/misc/util.h"
|
|
#include "ultima/ultima8/games/game_data.h"
|
|
#include "ultima/ultima8/usecode/usecode_flex.h"
|
|
#include "ultima/ultima8/gfx/main_shape_archive.h"
|
|
#include "ultima/ultima8/gfx/fonts/font_shape_archive.h"
|
|
#include "ultima/ultima8/gfx/gump_shape_archive.h"
|
|
#include "ultima/ultima8/world/map_glob.h"
|
|
#include "ultima/ultima8/world/fire_type_table.h"
|
|
#include "ultima/ultima8/world/actors/npc_dat.h"
|
|
#include "ultima/ultima8/world/actors/combat_dat.h"
|
|
#include "ultima/ultima8/gfx/palette_manager.h"
|
|
#include "ultima/ultima8/gfx/shape.h"
|
|
#include "ultima/ultima8/gfx/wpn_ovlay_dat.h"
|
|
#include "ultima/ultima8/gfx/fonts/font_manager.h"
|
|
#include "ultima/ultima8/games/game_info.h"
|
|
#include "ultima/ultima8/gumps/weasel_dat.h"
|
|
#include "ultima/ultima8/conf/config_file_manager.h"
|
|
#include "ultima/ultima8/convert/crusader/convert_shape_crusader.h"
|
|
#include "ultima/ultima8/audio/music_flex.h"
|
|
#include "ultima/ultima8/audio/speech_flex.h"
|
|
|
|
namespace Ultima {
|
|
namespace Ultima8 {
|
|
|
|
GameData *GameData::_gameData = nullptr;
|
|
|
|
GameData::GameData(GameInfo *gameInfo)
|
|
: _fixed(nullptr), _mainShapes(nullptr), _mainUsecode(nullptr), _globs(),
|
|
_fonts(nullptr), _gumps(nullptr), _mouse(nullptr), _music(nullptr),
|
|
_weaponOverlay(nullptr), _soundFlex(nullptr), _gameInfo(gameInfo) {
|
|
debug(1, "Creating GameData...");
|
|
|
|
_gameData = this;
|
|
_speech.resize(1024);
|
|
}
|
|
|
|
GameData::~GameData() {
|
|
debug(1, "Destroying GameData...");
|
|
|
|
delete _fixed;
|
|
_fixed = nullptr;
|
|
|
|
delete _mainShapes;
|
|
_mainShapes = nullptr;
|
|
|
|
delete _mainUsecode;
|
|
_mainUsecode = nullptr;
|
|
|
|
for (unsigned int i = 0; i < _globs.size(); ++i)
|
|
delete _globs[i];
|
|
_globs.clear();
|
|
|
|
delete _fonts;
|
|
_fonts = nullptr;
|
|
|
|
delete _gumps;
|
|
_gumps = nullptr;
|
|
|
|
delete _mouse;
|
|
_mouse = nullptr;
|
|
|
|
delete _music;
|
|
_music = nullptr;
|
|
|
|
delete _weaponOverlay;
|
|
_weaponOverlay = nullptr;
|
|
|
|
delete _soundFlex;
|
|
_soundFlex = nullptr;
|
|
|
|
for (unsigned int i = 0; i < _npcTable.size(); ++i)
|
|
delete _npcTable[i];
|
|
_npcTable.clear();
|
|
|
|
_gameData = nullptr;
|
|
|
|
for (unsigned int i = 0; i < _speech.size(); ++i) {
|
|
SpeechFlex **s = _speech[i];
|
|
if (s) delete *s;
|
|
delete s;
|
|
}
|
|
_speech.clear();
|
|
}
|
|
|
|
MapGlob *GameData::getGlob(uint32 glob) const {
|
|
if (glob < _globs.size())
|
|
return _globs[glob];
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
ShapeArchive *GameData::getShapeFlex(uint16 flexId) const {
|
|
switch (flexId) {
|
|
case MAINSHAPES:
|
|
return _mainShapes;
|
|
case GUMPS:
|
|
return _gumps;
|
|
default:
|
|
break;
|
|
};
|
|
return nullptr;
|
|
}
|
|
|
|
Shape *GameData::getShape(FrameID f) const {
|
|
ShapeArchive *sf = getShapeFlex(f._flexId);
|
|
if (!sf)
|
|
return nullptr;
|
|
Shape *shape = sf->getShape(f._shapeNum);
|
|
return shape;
|
|
}
|
|
|
|
const ShapeFrame *GameData::getFrame(FrameID f) const {
|
|
const Shape *shape = getShape(f);
|
|
if (!shape)
|
|
return nullptr;
|
|
const ShapeFrame *frame = shape->getFrame(f._frameNum);
|
|
return frame;
|
|
}
|
|
|
|
void GameData::loadTranslation() {
|
|
ConfigFileManager *config = ConfigFileManager::get_instance();
|
|
Common::Path translationfile;
|
|
|
|
if (_gameInfo->_type == GameInfo::GAME_U8) {
|
|
switch (_gameInfo->_language) {
|
|
case GameInfo::GAMELANG_ENGLISH:
|
|
// using "translation" to enable bug fixes
|
|
translationfile = "u8english.ini";
|
|
break;
|
|
case GameInfo::GAMELANG_FRENCH:
|
|
translationfile = "u8french.ini";
|
|
break;
|
|
case GameInfo::GAMELANG_GERMAN:
|
|
translationfile = "u8german.ini";
|
|
break;
|
|
case GameInfo::GAMELANG_SPANISH:
|
|
translationfile = "u8spanish.ini";
|
|
break;
|
|
case GameInfo::GAMELANG_JAPANESE:
|
|
translationfile = "u8japanese.ini";
|
|
break;
|
|
default:
|
|
warning("Unknown language.");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!translationfile.empty()) {
|
|
debug(1, "Loading translation: %s", translationfile.toString().c_str());
|
|
|
|
config->readConfigFile(translationfile, "language");
|
|
}
|
|
}
|
|
|
|
Std::string GameData::translate(const Std::string &text) {
|
|
// TODO: maybe cache these lookups? config calls may be expensive
|
|
ConfigFileManager *config = ConfigFileManager::get_instance();
|
|
Std::string trans;
|
|
if (config->get("language", "text", text, trans)) {
|
|
return trans;
|
|
}
|
|
return text;
|
|
}
|
|
|
|
FrameID GameData::translate(FrameID f) {
|
|
// TODO: maybe cache these lookups? config calls may be expensive
|
|
// TODO: add any non-gump shapes when applicable
|
|
// TODO: allow translations to be in another shapeflex
|
|
|
|
ConfigFileManager *config = ConfigFileManager::get_instance();
|
|
Std::string category = "language";
|
|
Std::string section;
|
|
|
|
switch (f._flexId) {
|
|
case GUMPS:
|
|
section = "gumps";
|
|
break;
|
|
default:
|
|
return f;
|
|
}
|
|
|
|
char buf[100];
|
|
Common::sprintf_s(buf, "%d,%d", f._shapeNum, f._frameNum);
|
|
|
|
Std::string key = buf;
|
|
Std::string trans;
|
|
if (!config->get(category, section, key, trans)) {
|
|
return f;
|
|
}
|
|
|
|
FrameID t;
|
|
t._flexId = f._flexId;
|
|
int n = sscanf(trans.c_str(), "%u,%u", &t._shapeNum, &t._frameNum);
|
|
if (n != 2) {
|
|
warning("Invalid shape translation: %s", trans.c_str());
|
|
return f;
|
|
}
|
|
|
|
return t;
|
|
}
|
|
|
|
void GameData::loadU8Data() {
|
|
auto *fd = new Common::File();
|
|
if (!fd->open("static/fixed.dat"))
|
|
error("Unable to load static/fixed.dat");
|
|
|
|
_fixed = new RawArchive(fd);
|
|
|
|
char langletter = _gameInfo->getLanguageUsecodeLetter();
|
|
if (!langletter)
|
|
error("Unknown language. Unable to open usecode");
|
|
|
|
Std::string filename = "usecode/";
|
|
filename += langletter;
|
|
filename += "usecode.flx";
|
|
|
|
|
|
auto *uds = new Common::File();
|
|
if (!uds->open(Common::Path(filename)))
|
|
error("Unable to load %s", filename.c_str());
|
|
|
|
_mainUsecode = new UsecodeFlex(uds);
|
|
|
|
// Load main shapes
|
|
debug(1, "Load Shapes");
|
|
auto *sf = new Common::File();
|
|
if (!(sf->open("static/u8shapes.flx") || sf->open("static/u8shapes.cmp")))
|
|
error("Unable to load static/u8shapes.flx or static/u8shapes.cmp");
|
|
|
|
_mainShapes = new MainShapeArchive(sf, MAINSHAPES,
|
|
PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
|
|
|
|
// Load weapon, armour info
|
|
ConfigFileManager *config = ConfigFileManager::get_instance();
|
|
config->readConfigFile("u8weapons.ini", "weapons");
|
|
config->readConfigFile("u8armour.ini", "armour");
|
|
config->readConfigFile("u8monsters.ini", "monsters");
|
|
config->readConfigFile("u8game.ini", "game");
|
|
|
|
// Load typeflags
|
|
auto *tfs = new Common::File();
|
|
if (!tfs->open("static/typeflag.dat"))
|
|
error("Unable to load static/typeflag.dat");
|
|
|
|
_mainShapes->loadTypeFlags(tfs);
|
|
delete tfs;
|
|
|
|
// Load animdat
|
|
auto *af = new Common::File();
|
|
if (!af->open("static/anim.dat"))
|
|
error("Unable to load static/anim.dat");
|
|
|
|
_mainShapes->loadAnimDat(af);
|
|
delete af;
|
|
|
|
// Load weapon overlay data
|
|
auto *wod = new Common::File();
|
|
if (!wod->open("static/wpnovlay.dat"))
|
|
error("Unable to load static/wpnovlay.dat");
|
|
|
|
RawArchive *overlayflex = new RawArchive(wod);
|
|
_weaponOverlay = new WpnOvlayDat();
|
|
_weaponOverlay->load(overlayflex);
|
|
delete overlayflex;
|
|
|
|
// Load _globs
|
|
auto *gds = new Common::File();
|
|
if (!gds->open("static/glob.flx"))
|
|
error("Unable to load static/glob.flx");
|
|
|
|
RawArchive *globflex = new RawArchive(gds);
|
|
_globs.clear();
|
|
_globs.resize(globflex->getCount());
|
|
for (unsigned int i = 0; i < globflex->getCount(); ++i) {
|
|
MapGlob *glob = 0;
|
|
Common::SeekableReadStream *globrs = globflex->get_datasource(i);
|
|
|
|
if (globrs && globrs->size()) {
|
|
glob = new MapGlob();
|
|
glob->read(globrs);
|
|
}
|
|
delete globrs;
|
|
|
|
_globs[i] = glob;
|
|
}
|
|
delete globflex;
|
|
|
|
// Load fonts
|
|
auto *fds = new Common::File();
|
|
if (!fds->open("static/u8fonts.flx"))
|
|
error("Unable to load static/u8fonts.flx");
|
|
|
|
_fonts = new FontShapeArchive(fds, OTHER,
|
|
PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
|
|
_fonts->setHVLeads();
|
|
|
|
// Load \mouse
|
|
auto *msds = new Common::File();
|
|
if (!msds->open("static/u8mouse.shp"))
|
|
error("Unable to load static/u8mouse.shp");
|
|
|
|
_mouse = new Shape(msds, 0);
|
|
_mouse->setPalette(PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
|
|
delete msds;
|
|
|
|
auto *gumpds = new Common::File();
|
|
if (!gumpds->open("static/u8gumps.flx"))
|
|
error("Unable to load static/u8gumps.flx");
|
|
|
|
_gumps = new GumpShapeArchive(gumpds, GUMPS,
|
|
PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
|
|
|
|
auto *gumpageds = new Common::File();
|
|
if (!gumpageds->open("static/gumpage.dat"))
|
|
error("Unable to load static/gumpage.dat");
|
|
|
|
_gumps->loadGumpage(gumpageds);
|
|
delete gumpageds;
|
|
|
|
|
|
auto *mf = new Common::File();
|
|
if (!mf->open("sound/music.flx"))
|
|
error("Unable to load sound/music.flx");
|
|
|
|
_music = new MusicFlex(mf);
|
|
|
|
auto *sndflx = new Common::File();
|
|
if (!sndflx->open("sound/sound.flx"))
|
|
error("Unable to load sound/sound.flx");
|
|
|
|
_soundFlex = new SoundFlex(sndflx);
|
|
|
|
loadTranslation();
|
|
}
|
|
|
|
void GameData::setupFontOverrides() {
|
|
setupTTFOverrides("game", false);
|
|
|
|
if (_gameInfo->_language == GameInfo::GAMELANG_JAPANESE)
|
|
setupJPOverrides();
|
|
}
|
|
|
|
void GameData::setupJPOverrides() {
|
|
ConfigFileManager *config = ConfigFileManager::get_instance();
|
|
FontManager *fontmanager = FontManager::get_instance();
|
|
KeyMap jpkeyvals;
|
|
|
|
jpkeyvals = config->listKeyValues("language", "jpfonts");
|
|
for (const auto &i : jpkeyvals) {
|
|
int fontnum = atoi(i._key.c_str());
|
|
const Std::string &fontdesc = i._value;
|
|
|
|
Std::vector<Std::string> vals;
|
|
SplitString(fontdesc, ',', vals);
|
|
if (vals.size() != 2) {
|
|
warning("Invalid jpfont override: %s", fontdesc.c_str());
|
|
continue;
|
|
}
|
|
|
|
unsigned int jpfontnum = atoi(vals[0].c_str());
|
|
uint32 col32 = strtol(vals[1].c_str(), 0, 0);
|
|
|
|
if (!fontmanager->addJPOverride(fontnum, jpfontnum, col32)) {
|
|
warning("failed to setup jpfont override for font %d", fontnum);
|
|
}
|
|
}
|
|
|
|
setupTTFOverrides("language", true);
|
|
}
|
|
|
|
void GameData::setupTTFOverrides(const char *category, bool SJIS) {
|
|
ConfigFileManager *config = ConfigFileManager::get_instance();
|
|
FontManager *fontmanager = FontManager::get_instance();
|
|
KeyMap ttfkeyvals;
|
|
|
|
bool overridefonts = ConfMan.getBool("font_override");
|
|
if (!overridefonts) return;
|
|
|
|
ttfkeyvals = config->listKeyValues(category, "fontoverride");
|
|
for (const auto &i : ttfkeyvals) {
|
|
int fontnum = atoi(i._key.c_str());
|
|
const Std::string &fontdesc = i._value;
|
|
|
|
Std::vector<Std::string> vals;
|
|
SplitString(fontdesc, ',', vals);
|
|
if (vals.size() != 4) {
|
|
warning("Invalid ttf override: %s", fontdesc.c_str());
|
|
continue;
|
|
}
|
|
|
|
const Common::Path filename(vals[0]);
|
|
int pointsize = atoi(vals[1].c_str());
|
|
uint32 col32 = strtol(vals[2].c_str(), 0, 0);
|
|
int border = atoi(vals[3].c_str());
|
|
|
|
if (!fontmanager->addTTFOverride(fontnum, filename, pointsize,
|
|
col32, border, SJIS)) {
|
|
warning("failed to setup ttf override for font %d", fontnum);
|
|
}
|
|
}
|
|
}
|
|
|
|
SpeechFlex *GameData::getSpeechFlex(uint32 shapeNum) {
|
|
if (shapeNum >= _speech.size())
|
|
return nullptr;
|
|
|
|
SpeechFlex **s = _speech[shapeNum];
|
|
if (s)
|
|
return *s;
|
|
|
|
char langletter = _gameInfo->getLanguageFileLetter();
|
|
if (!langletter) {
|
|
warning("GameData::getSpeechFlex: Unknown language.");
|
|
return nullptr;
|
|
}
|
|
|
|
Common::Path path(Common::String::format("sound/%c%i.flx", langletter, shapeNum));
|
|
|
|
auto *sflx = new Common::File();
|
|
if (!sflx->open(path)) {
|
|
delete sflx;
|
|
return nullptr;
|
|
}
|
|
|
|
s = new SpeechFlex *;
|
|
*s = new SpeechFlex(sflx);
|
|
_speech[shapeNum] = s;
|
|
|
|
return *s;
|
|
}
|
|
|
|
const NPCDat *GameData::getNPCData(uint16 entry) const {
|
|
if (entry < _npcTable.size()) {
|
|
return _npcTable[entry];
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
const NPCDat *GameData::getNPCDataForShape(uint16 shapeno) const {
|
|
for (const auto *npcdat : _npcTable) {
|
|
if (npcdat->getShapeNo() == shapeno)
|
|
return npcdat;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
const CombatDat *GameData::getCombatDat(uint16 entry) const {
|
|
if (entry < _combatData.size()) {
|
|
return _combatData[entry];
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
const WeaselDat *GameData::getWeaselDat(uint16 entry) const {
|
|
if (entry < _weaselData.size()) {
|
|
return _weaselData[entry];
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
const FireType *GameData::getFireType(uint16 type) const {
|
|
return FireTypeTable::get(type);
|
|
}
|
|
|
|
void GameData::loadRemorseData() {
|
|
auto *fd = new Common::File();
|
|
if (!fd->open("static/fixed.dat"))
|
|
error("Unable to load static/fixed.dat");
|
|
|
|
_fixed = new RawArchive(fd);
|
|
|
|
char langletter = _gameInfo->getLanguageUsecodeLetter();
|
|
if (!langletter)
|
|
error("Unknown language. Unable to open usecode");
|
|
|
|
Std::string filename = "usecode/";
|
|
filename += langletter;
|
|
filename += "usecode.flx";
|
|
|
|
auto *uds = new Common::File();
|
|
if (!uds->open(filename.c_str()))
|
|
error("Unable to load %s", filename.c_str());
|
|
|
|
_mainUsecode = new UsecodeFlex(uds);
|
|
|
|
// Load main shapes
|
|
debug(1, "Load Shapes");
|
|
auto *sf = new Common::File();
|
|
if (!sf->open("static/shapes.flx"))
|
|
error("Unable to load static/shapes.flx");
|
|
|
|
_mainShapes = new MainShapeArchive(sf, MAINSHAPES,
|
|
PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game),
|
|
&CrusaderShapeFormat);
|
|
|
|
ConfigFileManager *config = ConfigFileManager::get_instance();
|
|
// Load weapon, armour info
|
|
if (_gameInfo->_type == GameInfo::GAME_REMORSE)
|
|
config->readConfigFile("remorseweapons.ini", "weapons");
|
|
else
|
|
config->readConfigFile("regretweapons.ini", "weapons");
|
|
|
|
config->readConfigFile("remorsegame.ini", "game");
|
|
|
|
// Load typeflags
|
|
auto *tfs = new Common::File();
|
|
if (!tfs->open("static/typeflag.dat"))
|
|
error("Unable to load static/typeflag.dat");
|
|
|
|
_mainShapes->loadTypeFlags(tfs);
|
|
delete tfs;
|
|
|
|
// Load animdat
|
|
auto *af = new Common::File();
|
|
if (!af->open("static/anim.dat"))
|
|
error("Unable to load static/anim.dat");
|
|
|
|
_mainShapes->loadAnimDat(af);
|
|
delete af;
|
|
|
|
// Load weapon overlay data
|
|
auto *wod = new Common::File();
|
|
if (!wod->open("static/wpnovlay.dat"))
|
|
error("Unable to load static/wpnovlay.dat");
|
|
|
|
RawArchive *overlayflex = new RawArchive(wod);
|
|
_weaponOverlay = new WpnOvlayDat();
|
|
_weaponOverlay->load(overlayflex);
|
|
delete overlayflex;
|
|
|
|
// Load globs
|
|
auto *gds = new Common::File();
|
|
if (!gds->open("static/glob.flx"))
|
|
error("Unable to load static/glob.flx");
|
|
|
|
RawArchive *globflex = new RawArchive(gds);
|
|
_globs.clear();
|
|
_globs.resize(globflex->getCount());
|
|
for (unsigned int i = 0; i < globflex->getCount(); ++i) {
|
|
MapGlob *glob = 0;
|
|
Common::SeekableReadStream *globrs = globflex->get_datasource(i);
|
|
|
|
if (globrs && globrs->size()) {
|
|
glob = new MapGlob();
|
|
glob->read(globrs);
|
|
}
|
|
delete globrs;
|
|
|
|
_globs[i] = glob;
|
|
}
|
|
delete globflex;
|
|
|
|
// Load fonts
|
|
auto *fds = new Common::File();
|
|
if (!fds->open("static/fonts.flx"))
|
|
error("Unable to load static/fonts.flx");
|
|
|
|
_fonts = new FontShapeArchive(fds, OTHER,
|
|
PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
|
|
_fonts->setHVLeads();
|
|
|
|
// Load mouse
|
|
auto *msds = new Common::File();
|
|
if (!msds->open("static/mouse.shp"))
|
|
error("Unable to load static/mouse.shp");
|
|
|
|
_mouse = new Shape(msds, 0);
|
|
_mouse->setPalette(PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
|
|
delete msds;
|
|
|
|
auto *gumpds = new Common::File();
|
|
if (!gumpds->open("static/gumps.flx"))
|
|
error("Unable to load static/gumps.flx");
|
|
|
|
_gumps = new GumpShapeArchive(gumpds, GUMPS,
|
|
PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
|
|
|
|
auto *dtableds = new Common::File();
|
|
if (!dtableds->open("static/dtable.flx"))
|
|
error("Unable to load static/dtable.flx");
|
|
|
|
RawArchive *dtableflex = new RawArchive(dtableds);
|
|
_npcTable = NPCDat::load(dtableflex);
|
|
delete dtableflex;
|
|
|
|
auto *damageds = new Common::File();
|
|
if (!damageds->open("static/damage.flx"))
|
|
error("Unable to load static/damage.flx");
|
|
|
|
RawArchive *damageflex = new RawArchive(damageds);
|
|
if (damageflex->getCount() != 1)
|
|
error("static/damage.flx appears corrupted");
|
|
|
|
_mainShapes->loadDamageDat(damageflex->get_datasource(0));
|
|
|
|
delete damageflex;
|
|
|
|
auto *combatds = new Common::File();
|
|
if (!combatds->open("static/combat.dat"))
|
|
error("Unable to load static/combat.dat");
|
|
|
|
RawArchive *combatflex = new RawArchive(combatds);
|
|
_combatData.clear();
|
|
_combatData.resize(combatflex->getCount());
|
|
for (uint32 i = 0; i < combatflex->getCount(); i++) {
|
|
Common::SeekableReadStream *combatflexrs = combatflex->get_datasource(i);
|
|
|
|
if (combatflexrs && combatflexrs->size() > 20) {
|
|
_combatData[i] = new CombatDat(*combatflexrs);
|
|
}
|
|
delete combatflexrs;
|
|
}
|
|
|
|
delete combatflex;
|
|
|
|
auto *stuffds = new Common::File();
|
|
if (!stuffds->open("static/stuff.dat"))
|
|
error("Unable to load static/stuff.dat");
|
|
|
|
// Weasel shop data.
|
|
// 14 blocks of 323 bytes, references like W01 and I07
|
|
// (weapon and inventory)
|
|
while (!stuffds->eos()) {
|
|
WeaselDat *data = new WeaselDat(stuffds);
|
|
_weaselData.push_back(data);
|
|
}
|
|
|
|
delete stuffds;
|
|
|
|
auto *xformpalds = new Common::File();
|
|
if (!xformpalds->open("static/xformpal.dat"))
|
|
error("Unable to load static/xformpal.dat");
|
|
RawArchive *xformpalflex = new RawArchive(xformpalds);
|
|
|
|
// TODO: What's in this flex?
|
|
// Object 1: 32 bytes
|
|
// Object 2: 2304 bytes - presumably data for 3 palettes == 768 * 3
|
|
// almost no low numbers (so not raw palette data, would be missing black..)
|
|
|
|
delete xformpalflex;
|
|
|
|
// Note: No MusicFlex for Remorse, as the music is all in different AMF files.
|
|
// The remorse_music_process will load them.
|
|
|
|
auto *sndflx = new Common::File();
|
|
if (!sndflx->open("sound/sound.flx"))
|
|
error("Unable to load sound/sound.flx");
|
|
|
|
_soundFlex = new SoundFlex(sndflx);
|
|
|
|
loadTranslation();
|
|
}
|
|
|
|
} // End of namespace Ultima8
|
|
} // End of namespace Ultima
|